Multiple "cmp"s chained one after another

Glauco Silva glauco.silva at cenpra.gov.br
Mon May 16 09:16:18 EDT 2005


You can try this :
>>> l = [(2001, 5, 2),(2111,3,3),(1984, 3, 1), (2001, 1, 1)]
>>> l.sort(lambda x = l[0],y = l[1] : cmp((x[1],x[2]),(y[1],y[2])))

----- Original Message ----- 
From: "Volker Grabsch" <volker_grabsch at v.notjusthosting.com>
To: <python-list at python.org>
Sent: Saturday, May 14, 2005 7:09 AM
Subject: Multiple "cmp"s chained one after another


Hello!

Ich just found a very nice 'pythonic' solution for an often appearing
problem. I didn't find it documented anywhere, so I'm posting it here.
If this isn't new in any way, I'd really like to get to know it.

Example problem:
I have some "datetime" objects and want to sort them, as here:

birthdays = [d1,d2,d3,d4]
birthdays.sort()

However, I don't want to sort them the default way. These are birthdays,
so only the month and day do matter, not the year. E.g.:

2003-01-01  should be smaller than  1984-05-01

So I have to write the comparison on my own, e.g.

def cmp_birthdays(d1,d2):
if d1.month > d2.month: return 1
if d1.month < d2.month: return -1
if d1.day > d2.day: return 1
if d1.day < d2.day: return -1
return 0

...
birthdays.sort(cmp_birthdays)

This implementation of cmp_birthdays is very ugly. Image you want to
chain more than 2 values in that "cmp_birthdays". I also want to use the
builtin "cmp" function, not ">" and "<".

After thinking some minutes about it, I found a very nice solution:
I have some "cmp"s one aftter another. If one if them return 1 oder -1,
it sould be returned. If it returns 0, the next "cmp" is used. In other
words: I have a sequence of numbers, and want to get the first one that
is not 0. (or return 0, if all numbers were 0)

But this is exactly what the "or" operator does, due to short-circuit
evaluation. In this example, that means:

def cmp_bithdays(d1,d2):
return cmp(d1.month,d2.month) or cmp(d1.day,d2.day)

The generic pattern is:

return cmp(...) or cmp (...) or cmp(...) or ...

I'm not sure whether this pattern is already a "common recipe", but
I found it to be a very nice idea. :-)

Any opinions?


Greets,

Volker

-- 
Volker Grabsch
---<<(())>>---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}




-- 
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.308 / Virus Database: 266.11.10 - Release Date: 13/5/2005




More information about the Python-list mailing list