Re: Coming from delphi - looking for an IDE - willing to spend money

2006-04-24 Thread Dave Hughes
Just call me James wrote:

> Hi,
> 
> Coming away from the luxury of the delphi IDE has been something of a
> shock.
> 
> As a consequence I've become aware that maybe I need to spend some
> money on a python IDE.
> 
> As a beginner I reckon integrated debugging would be helpful.
> 
> Does anyone have any advice or suggestions? So far I've glanced at
> Komodo, but as a beginner I'm not in a positon to evaluate it.
> 
> thanks for exprienced advice,
> 
> Greg

I sympathize entirely (I've been a Delphi user since v2 and have yet to
find an equally competent IDE for just about any language). Here's the
list of IDEs I went through in my transition from Delphi to Python (I
started off hacking around with Python on my Linux box with vim, but
quickly went searching for something a bit more comprehensive and
specific to the language):


Boa Constructor
http://boa-constructor.sourceforge.net/

Heavy-weight IDE designed to be a sort of Delphi-for-Python. Includes
integrated debugging, visual form designer and property inspector (uses
wxWindows as its GUI framework) and a pretty cool editor (based on the
Scintilla component).

It's still a bit flaky in some places, but it's certainly usable. That
said, my machine isn't exactly fast: I eventually got fed up with the
slow speed and went hunting for something a bit quicker...


Stani's Python Editor (SPE)
http://pythonide.stani.be/

Heavy-weight editor (based on Scintilla IIRC) with Blender integration.
Uses wxGlade or XRCed as visual form designers. Didn't try this one for
long; for some reason the interface just didn't "feel" right. Then
again, it's open-source and many swear by it so you may as well give it
a shot.


TruStudio
http://www.xored.com/trustudio

Heavy-weight IDE (based on Eclipse). Gave it a whirl but as you can
imagine, if my machine was slow with Boa Constructor, the Java-based
Eclipse was just glacial... Urgh.


PyScripter
http://mmm-experts.com/Products.aspx?ProductId=4

Light-weight IDE with integrated debugging (no visual form designer). I
was interested in this as it's written in Delphi. Hence, it's pretty
damned fast, small, and serves as an interesting example of integrating
the Python interpreter in Delphi applications (something I was
interested in doing, though I haven't had an actual need to do so yet).

Unfortunately, the editor component used is SynEdit (which, being a
Delphi user I'm guessing you've probably heard of and/or used).
SynEdit's a great component for small scale editing, but it's just got
too many bugs when dealing with large files or long editing sessions,
and lacks some of Scintilla's neat features like code-folding (given
that the source for PyScripter is available it might be interesting to
try replacing the SynEdit editor with Scintilla since there's a Delphi
interface for Scintilla available ... although I suspect it'd be a
pretty big job).


Notepad2
http://www.flos-freeware.ch/notepad2.html

Light-weight editor (based on Scintilla). Little more than a notepad
replacement (no integrated debugger or visual stuff) with those
features you always wanted in notepad (support for UNIX line breaks,
syntax highlighting, etc).


At this point I realized I'd gone from heavy-weight full-blown IDEs
with integrated debugging, to heavy-weight editors, to light-weight
editors, and back to using stack traces and the odd print statement for
debugging. However, I also found (to my surprise) that I'd got
comfortable enough with Python that not having integrated debugging no
longer bothered me. I realized what I was really searching for was a
small, fast, powerful editor...

And so it was that after 2 or 3 weeks of hunting for the best IDE for
me, I wound up right back where I started: vim :-)

Still, I consider the journey to have been worth it (e.g. the
integrated debugger in Boa helped me learn Python that much quicker by
making it easy to spot my beginners mistakes).

You might want to check out eric3 as well. I haven't tried it but it's
another one some people swear by:
http://www.die-offenbachs.de/detlev/eric3.html


Good luck!

Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Counting elements in a list wildcard

2006-04-24 Thread Dave Hughes
hawkesed wrote:

> If I have a list, say of names. And I want to count all the people
> named, say, Susie, but I don't care exactly how they spell it (ie,
> Susy, Susi, Susie all work.) how would I do this? Set up a regular
> expression inside the count? Is there a wildcard variable I can use?
> Here is the code for the non-fuzzy way:
> lstNames.count("Susie")
> Any ideas? Is this something you wouldn't expect count to do?
> Thanks y'all from a newbie.
> Ed

You might want to check out the SoundEx and MetaPhone algorithms which
provide approximations of the "sound" of a word based on spelling
(assuming English pronunciations).

Apparently a soundex module used to be built into Python but was
removed in 2.0. You can find several implementations on the 'net, for
example:

http://orca.mojam.com/~skip/python/soundex.py
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52213

MetaPhone is generally considered better than SoundEx for "sounds-like"
matching, although it's considerably more complex (IIRC, although it's
been a long time since I wrote an implementation of either in any
language). A Python MetaPhone implementations (there must be more than
this one?):

http://joelspeters.com/awesomecode/

Another algorithm that might interest isn't based on "sounds-like" but
instead computes the number of transforms necessary to get from one
word to another: the Levenshtein distance. A C based implementation
(with Python interface) is available:

http://trific.ath.cx/resources/python/levenshtein/

Whichever algorithm you go with, you'll wind up with some sort of
"similar" function which could be applied in a similar manner to Ben's
example (I've just mocked up the following -- it's not an actual
session):

>>> import soundex
>>> import metaphone
>>> import levenshtein
>>> my_strings = ['Bob', 'Sally', 'Susi', 'Dick', 'Susy', 'Jane' ]
>>> found_suzys = [s for s in my_strings if
soundsex.sounds_similar(s, 'Susy')]
>>> found_suzys = [s for s in my_strings if
metaphone.sounds_similar(s, 'Susy')]
>>> found_suzys = [s for s in my_strings if levenshtein.distance(s,
'Susy') < 4]
>>> found_suzys
['Susi', 'Susy'] (one hopes anyway!)


HTH,

Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Strange constructor behaviour (or not?)

2006-04-28 Thread Dave Hughes
Rolf Wester wrote:

> Hi,
> 
> when defining:
> 
> class A:
>   def __init__(self, l=[]):
>   self.l = l
> a = A()
> a.l.append()
> b = A()
> print a.l
> 
> I get the output
> 
> []
> 
> instead of an empty list. I guess it's because the default value in
> the constructor is constructed once and whenever the constructor is
> called without l being specified.

Exactly right. See Python FAQ item 1.4.22
(http://www.python.org/doc/faq/general/#why-are-default-values-shared-be
tween-objects)

> My work around is:
> 
> class A:
>   def __init__(self, l=None):
>   if l == None:
>   self.l = []
>   else:
>   self.l = l
> 
> Is there a way to take the first definition but force the constructor
> to create a new empty list every time it is called?

Not as far as I know. Worth reading the above FAQ as it also contains
an interesting use of this side-effect.


Dave.

-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: time conversions [hh:mm:ss.ms <-> sec(.ms)

2006-04-28 Thread Dave Hughes
kpp9c wrote:

> Hi,
> 
> I was looking at python & datetime and hoping that it would already
> have
> a method/func to translate time formats. I need to translate seconds
> to hh:mm:ss.ms and vice versa and would like the ability to do some
> basic arithmetic in these formats. I think that there just has to be a
> package
> or module out there that already does this with reasonable speed and
> accuracy.
> 
> Sadly, i do indeed need both reasonable speed and accuracy since i
> will be adding up huge masses of small events (around 10 to 60 ms
> milliseconds
> in length) to create cloud like textures for real time audio/video at
> high sampling rates.
> 
> i googled for hh:mm:ss.ms + python and didn't find much...
> 
> best,
> 
> -kp---
> 
> [mac os x w/ python 2.4.1]

Hmmm ... not difficult to do, but it's the "speed" bit that's tricky.
Here's quick and dirty implementation, but I wouldn't place any bets on
it being fast (or accurate enough for that matter!)

#!/bin/env python
# vim: set noet sw=4 ts=4:

import datetime

def secs2time(s):
ms = int((s - int(s)) * 100)
s = int(s)
# Get rid of this line if s will never exceed 86400
while s >= 24*60*60: s -= 24*60*60
h = s / (60*60)
s -= h*60*60
m = s / 60
s -= m*60
return datetime.time(h, m, s, ms)

def time2secs(d):
return d.hour*60*60 + d.minute*60 + d.second + \
(float(d.microsecond) / 100)

if __name__ == "__main__":
for i in (8.123, 0.0, 5873, 12345.6789):
print "%12.6f -> %15s -> %12.6f" % (
i,
secs2time(i),
time2secs(secs2time(i))
)
assert i == time2secs(secs2time(i))
from timeit import Timer
timer = Timer(
setup="from __main__ import time2secs, secs2time",  
stmt="time2secs(secs2time(12345.6789))")
count = 100
total = timer.timeit(count)
print "Time for %d invocations: %.10fs" % (count, total)
print "Time per invocation: %.10fs" % (total / count,)


And the output:

8.123000 -> 22:13:20.123000 -> 8.123000
0.00 ->00:00:00 -> 0.00
 5873.00 ->01:37:53 ->  5873.00
12345.678900 -> 03:25:45.678900 -> 12345.678900
Time for 100 invocations: 9.3959178925s
Time per invocation: 0.093959s


Huh ... what d'ya know ... good thing I ain't a betting man!


Dave.

-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Undocumented alternate form for %#f ?

2006-04-28 Thread Dave Hughes
Dino Viehland wrote:

> I'm assuming this is by-design, but it doesn't appear to be
> documented:
> 
> >>> '%8.f' % (-1)
> '  -1'
> >>> '%#8.f' % (-1)
> ' -1.'
> 
> 
> The docs list the alternate forms, but there isn't one listed for
> f/F.   It would seem the alternate form for floating points is
> truncate & round the floating point value, but always display the .
> at the end.  Is that correct?

The Python % operator follows the C sprintf function pretty darn
closely in behaviour (hardly surprising really, though I've never
peeked at the implementation). Hence "man sprintf" can provide some
clues here. From man sprintf on my Linux box:

#
The  value  should be converted to an ``alternate form''.  For o
conversions, the first character of the output  string  is  made
zero (by prefixing a 0 if it was not zero already).  For x and X
conversions, a non-zero result has the string `0x' (or `0X'  for
X  conversions) prepended to it.  For a, A, e, E, f, F, g, and G
conversions, the result will always  contain  a  decimal  point,
even  if  no digits follow it (normally, a decimal point appears
in the results of those conversions only if  a  digit  follows).
For g and G conversions, trailing zeros are not removed from the
result as they would otherwise be.  For other  conversions,  the
result is undefined.

Hence, I don't think it's the # doing the truncating here, but it
certainly is producing the mandatory decimal point. If you get rid of
the "." in the specification, it uses the default decimal precision (6):

>>> "%8f" % (-1)
'-1.00'
>>> "%#8f" % (-1)
'-1.00'

No difference with the alternate specification here as the precision is
non-zero. Again, from man sprintf:

The precision
[snip]
If the precision is given as
just `.', or the precision is negative, the precision is  taken  to  be
zero.   This  gives the minimum number of digits to appear for d, i, o,
u, x, and X conversions, the number of digits to appear after the radix
character  for  a, A, e, E, f, and F conversions, the maximum number of
significant digits for g and G conversions, or the  maximum  number  of
characters to be printed from a string for s and S conversions.


HTH,

Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: returning none when it should be returning a list?

2006-05-01 Thread Dave Hughes
Edward Elliott wrote:

> [EMAIL PROTECTED] wrote:
> > The function basically takes in a list of all the prime number
> > found, it takes the next number to be tested for (next) and the
> > limit it will go up to. It divide next by the list of previous
> > prime numbers if next is not bigger than lim, count up all the
> > times where it's not evenly divdided, if the result is equal the
> > length of prime number, then we have another prime number, lather
> > rinse and repeat :)
> 
> Your basic algorithm as described above sounds workable, but can be
> made more efficient (I didn't look closely at your code for bugs).  I
> won't even go near the complicated number theory algorithms.
> 
> 1. integer mod will be faster than floating point mod (unless you're
> getting into numbers too large to store efficiently as ints, but
> you'll probably run into other limitations before you get near that
> point in this code).
> 
> 2. you can stop as soon as you find a zero remainder, no need to keep
> testing the rest of the primes in the list.
> 
> 3. you can stop testing numbers at the halfway point.  there are no
> primes smaller than 2, so no number x can have a factor larger than
> x/2.
> 
> 4. in fact you can do even better.  a simple proof by contradiction
> shows that if primes 1..y don't divide x and y^2 > x then x must be
> prime.  put another way, once you test up to the square root of x,
> there's no point continuing.  if one factor were bigger than sqrt(x),
> the other would have to be smaller than sqrt(x).  but you've already
> tested the factors smaller than sqrt(x), so there can't be any
> factors.

The Prime Number article[1] on Wikipedia has a nice little Python
snippet implementing this algorithm (more or less). See the Finding
Prime Numbers section.

> 5. you can do better than checking every odd number (next+2) to find
> the next prime, but I'm too tired to look into it right now.  it may
> require more complex machinery.
> 
> Locating primes is an interesting challenge because of the seemingly
> endless grades of refinements over simple brute-force search.  Like I
> said though, if speed and size aren't concerns, your algorithm is
> fine.

Further reading: the Sieve of Eratosthenes[2] is a relatively simple
and fun little algorithm to implement (also has a size issue in that it
requires a list of numbers from 2 up to the largest number you wish to
test for primality, and I don't think it's any faster than the
algorithm above). A modern refinement called the Sieve of Atkin[3] is
also interesting, a bit faster, although rather more complicated.

If you want to look further into the subject, see the Primality Test
article[4] on Wikipedia (mentions things like probabilistic testing,
the Miller-Rabin primality test, and such like).

[1] http://en.wikipedia.org/wiki/Prime_number
[2] http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
[3] http://en.wikipedia.org/wiki/Sieve_of_Atkin
[4] http://en.wikipedia.org/wiki/Primality_test


Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: regd efficient methods to manipulate *large* files

2006-05-01 Thread Dave Hughes
Madhusudhanan Chandrasekaran wrote:

> Hi:
> 
>   This question is not directed "entirely" at python only. But since
> I want to know how to do it in python, I am posting here.
> 
> 
> I am constructing a huge matrix (m x n), whose columns n are stored in
> smaller files. Once I read m such files, my matrix is complete. I
> want to pass this matrix as an input to another script of mine (I
> just have the binary.) Currently, the script reads a file (which is
> nothing but the matrix) and processes it. Is there any way of doing
> this in memory, without writing the matrix onto the disk?
> 
> Since I have to repeat my experimentation for multiple iterations, it
> becomes expensive to write the matrix onto the disk.
> 
> Thanks in advance. Help appreciated.
> 
> -Madhu

Basically, you're asking about Inter Process Communication (IPC), for
which Python provides several interfaces to mechanisms provided by the
operating system (whatever that may be). Here's a couple of commonly
used methods:

Redirected I/O

Have a look at the popen functions in the os module, or better still
the subprocess module (which is a higher level interface to the same
functionality). Specifically, the "Replacing the shell pipe line"
example in the subprocess module's documentation should be interesting:

  output=`dmesg | grep hda`
  ==>
  p1 = Popen(["dmesg"], stdout=PIPE)
  p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
  output = p2.communicate()[0]

Here, the stdout of the "dmesg" process has been redirected to the
stdin of the "grep" process. You could do something similar with your
two scripts: e.g., the first script simply writes the content of the
matrix in some format to stdout (e.g. print, sys.stdout.write), while
the second script reads the content of the matrix from stdin (e.g.
raw_input, sys.stdin.read). Here's some brutally simplistic scripts
that demonstrate the method:

in.py
=
#!/bin/env python
#
# I read integers from stdin until I encounter 0

import sys

while True:
i = int(sys.stdin.readline())
print "Read %d from stdin" % i
if i == 0:
break


out.py
==
#!/bin/env python
#
# I write some numbers to stdout

for i in [1, 2, 3, 4, 5, 0]:
print i


run.py
==
#!/bin/env python
#
# I run out.py and in.py with a pipe between them, capture the
# output of in.py and print it

from subprocess import Popen, PIPE

process1 = Popen(["./out.py"], stdout=PIPE)
process2 = Popen(["./in.py"], stdin=process1.stdout, stdout=PIPE)
output = process2.communicate()[0]

print output


Sockets

Another form of IPC uses sockets to communicate between two processes
(see the socket module or one of the higher level modules like
SocketServer). Hence, the second process would listen on a port
(presumably on the localhost interface, although there's no reason it
couldn't listen on a LAN interface for example), and the first process
connects to that port and sends the matrix data across it to the second
process.


Summary

Given that your second script currently reads a file containing the
complete matrix (if I understand your post correctly), it's probably
easiest for you to use the Redirected I/O method (as it's very similar
to reading a file, although there are some differences, and sometimes
one must be careful about closing pipe ends to avoid deadlocks).
However, the sockets method has the advantage that you can easily move
one of the processes onto a different machine.

There are other methods of IPC (for example, shared memory: see the
mmap module) however the two mentioned above are available on most
platforms whereas others may be specific to a given platform, or have
platform specific subtleties (for example, mmap is only available on
Windows and UNIX, and has a slightly different constructor on each).


HTH,

Dave.

-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: using ftplib

2006-05-01 Thread Dave Hughes
John Salerno wrote:

> I'm experimenting with this now and I'm a little confused about
> transferring commands. This might be more of an FTP question than
> strictly Python, but it's still related to how to use the ftplib
> methods.
> 
> Anyway, if what I want to do is send a command to change the file
> permission settings of a file (or files), I assume I would use
> transfercmd() and the command would be something like SITE CHMOD 755
> name.py, for example.
> 
> What I'm confused about is why the documentation says to send a PORT
> or PASV command as well. Is this just something that must be done
> before each command?
> 
> Also, in order to figure out what the FTP commands are to begin with,
> I did a little testing in FileZilla and I noted what was being
> displayed at the top (things like PORT xxx, STOR xxx, SITE CHMOD,
> etc. depending on what I was doing). So I assume these are the 'cmd'
> parameter. So here are a couple of questions:
> 
> 1. Are PORT/PASV necessary to start a transfer?

Indeed. FTP is a tricky (and _very_ old) protocol that does things in a
very different manner to the later (simpler) protocols like HTTP. Not
sure how familiar you are with FTP, so my apologies if I wind up
repeating stuff you know already:

FTP sessions typically have *two* connections: the "control"
connection, and the "data" connection. The control connection is from
the client to the server (typically port 21 on the server side), and is
used to send commands to the server and obtain responses.

The PORT command tells the server to open a data connection to the
client (yes, that's not a typo: from the server to the client) and the
parameters tell the server the address and port to connect to. This is
the "active" (or default) mode for FTP (although due to the heavy use
of NAT these days, "passive" mode is probably as, or more common in
practice).

The PASV command is the reverse of the PORT command: it requests the
server listen on a new port for a data connection from the client to
the server.

Data is never transferred over the control connection, it always goes
over the separate data connection, hence why PORT or PASV are required
before initiating a transfer.

See RFC 959 for the full spec (gawd, it's been a long time since I read
that ... amazed I still remember the number):
http://www.faqs.org/rfcs/rfc959.html

> 
> 2. Is the cmd parameter some kind of list, or is it just a string and
> you have to call a separate transfercmd() for each command?

Sorry, I haven't used ftplib yet, but a brief glance at the code
suggests to me that it's just a string and you probably do need to call
a separate transfercmd for each command.

> 3. My burning question: also during every transfer I made in
> FileZilla, I see that it sometimes sends a TYPE A or TYPE I command
> as well. What are these, and are they also necessary when I'm using
> transfercmd()?

TYPE I indicates that an "Image" transfer is to take place (though this
is more commonly referred to nowadays as a "binary" transfer). In an
binary transfer the data is transferred verbatim with no
transformations.

TYPE A indicates that an ASCII transfer is to take place. An ASCII
transfer is intended for use with text files and indicates that the
data should be transformed from the native text format on the client
platform to the native text format on the server platform. For example,
transferring a file from a DOS/Windows client to a UNIX/Linux platform
in ASCII mode would convert CRLF line endings (ASCII char 13 + ASCII
char 10) to LF line endings (ASCII char 10).

There are other transfer modes as well, though I forget exactly what
they are (there's probably one for EBCDIC  :-).

Take a look at the storbinary, storlines, retrbinary and retrlines
methods of the FTP object: looks like they perform the appropriate TYPE
command for you, then pass the specified command to transfercmd.


HTH,

Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: using ftplib

2006-05-02 Thread Dave Hughes
Steve Holden wrote:

> John Salerno wrote:
> [...]
> > 
> > So if I already have files on the server and I want to change file
> > permissions, do I need to mess with TYPE A/TYPE I commands, or are
> > those  strictly for when you transfer files? Because I just did a
> > quick test  of changing file permissions through my FTP program,
> > and it still sent a  TYPE A command in the process. I know that the
> > retr and stor methods  might do this automatically, but if I don't
> > need to use those, and just  need to use transfercmd (assuming this
> > is the right method to use when  changing file permissions), do I
> > need to manually send a TYPE A/I  command as well?
> 
> The answer is "probably not", but a better answer is "try it in the
> interactive interpreter and see".

As far as I recall your speculation is indeed correct: a TYPE command
is only necessary before a transfer (it's only used to transform data
passing over the secondary data connection). I'm reasonably certain you
don't need *anything* before a SITE command (like SITE CHMOD), not even
PORT or PASV (unless the specific SITE command being invoked requires a
data transfer, which CHMOD shouldn't). But as Steve suggests, the best
way to know for sure is to give it a whirl and see what happens :-)

Incidentally, you might like to experiment with the command line ftp
client. On both Linux and Windows, the "quote" command can be used to
send commands "raw" to the FTP server. For example:

ftp> quote SITE CHMOD 755 afile.py


Dave.

-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python's regular expression?

2006-05-10 Thread Dave Hughes
Dave Hansen wrote:

> On Wed, 10 May 2006 06:44:27 GMT in comp.lang.python, Edward Elliott
> <[EMAIL PROTECTED]> wrote:
> 
> 
> > 
> > Would I recommend perl for readable, maintainable code?  No, not
> > when better options like Python are available.  But it can be done
> > with some effort.
> 
> I'm reminded of a comment made a few years ago by John Levine,
> moderator of comp.compilers.  He said something like "It's clearly
> possible to write good code in C++.  It's just that no one does."

Reminds me of the quote that used to appear on the front page of the
ViewCVS project (seems to have gone now that they've moved and renamed
themselves to ViewVC). Can't recall the attribution off the top of my
head:

"[Perl] combines the power of C with the readability of PostScript"

Scathing ... but very funny :-)


Dave.

-- 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem involving sets...

2006-04-15 Thread Dave Hughes
Kent Johnson wrote:

> flamesrock wrote:
> > Kind of a fun but confusing problem...
> > 
> > I have two lists. Each list contains elements of two-element lists.
> > l1 = [['c1',1],['c2',2],['c3',4]]
> > l2 = [['c1',1],['c2',2],['c4',4],['c3',3]]
> > 
> > Exactly in this format, where
> > superlist[0][0] is always a string
> > superlist[0][1] is always an integer
> > 
> > Now what I would like to do is find the intersect of those two
> > super-lists based on superlist[0][0] and then compare the integers
> > to find ultimately:
> > A list of strings of the intersect of l1/l2, where the l1[x][1] >
> > l2[x][1]
> > In the case of the above example, that would be simply:
> > ['c3']
> 
> In [5]: l1 = [['c1',1],['c2',2],['c3',4]]
> 
> In [6]: l2 = [['c1',1],['c2',2],['c4',4],['c3',3]]
> 
> In [7]: d=dict(l1)
> 
> In [10]: [k for k,v in l2 if k in d and v < d[k]]
> Out[10]: ['c3']
> 
> Kent

The dict solution posted above is definitely better than the following,
but purely out of idle curiosity I was interested to see if this could
be done in one line using just list comprehensions ...

Python 2.4.2 (#1, Nov 15 2005, 15:54:06)
[GCC 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> l1 = [['c1',1],['c2',2],['c3',4]]
>>> l2 = [['c1',1],['c2',2],['c4',4],['c3',3]]
>>> [k2 for [k2,v2] in l2 if k2 in [k1 for k1,v1 in l1] and v2 < [v1
for k1,v1 in l1 if k1 == k2][0]]
['c3']

... yup :-)


Dave.
-- 

-- 
http://mail.python.org/mailman/listinfo/python-list