[Tutor] Logical Sorting

Kent Johnson kent37 at tds.net
Fri Jul 7 19:41:47 CEST 2006


Evan Klitzke wrote:
> Hi,
>
> I am trying to sort a list of directories that correspond to kernel
> sources under /usr/src/linux.  I wrote some code that gets a list like
> this:
> ['linux-2.6.9-gentoo-r4', 'linux-2.6.16-gentoo-r11/', 'linux-2.6.16-gentoo-r7/']
>
> When I sort the list, I want it to go from oldest (lowest version) to
> newest, so the sorted list should look like this:
> ['linux-2.6.9-gentoo-r4', 'linux-2.6.16-gentoo-r7/', 'linux-2.6.16-gentoo-r11/']
>
> The problem is that since the built in string comparisons compare
> character by character, so the sort puts 2.6.16 before 2.6.9, and -r11
> before -r7.  This is obviously not what I want.  My question is: are
> there any modules or built in methods that will do a logical sort on a
> list like this, and sort it the way I want, or will I have to write my
> own sorting function?

You don't have to write your own sorting function. You do have to write 
a function that extracts a key from a data item that will sort in the 
order you want. Here is a version that uses a regular expression to 
extract the four fields from the data, converts the numbers to integers, 
and returns a tuple of values that sorts correctly. It works with the 
data you show but it probably needs tweaks to be more robust, for 
example it will fail if the version is not three numbers or if the -rxx 
is missing.

In [1]: data = ['linux-2.6.9-gentoo-r4', 'linux-2.6.16-gentoo-r11/', 
'linux-2.6.16-gentoo-r7/']

In [2]: import re

In [3]: def makeKey(entry):
   ...:     m=re.search(r'-(\d+)\.(\d+)\.(\d+)-[^-]+-r(\d+)', entry)
   ...:     if not m: return entry
   ...:     return map(int, m.group(1, 2, 3, 4))
   ...:

In [4]: data.sort(key=makeKey)

In [5]: data
Out[5]:
['linux-2.6.9-gentoo-r4',
 'linux-2.6.16-gentoo-r7/',
 'linux-2.6.16-gentoo-r11/']

Kent



More information about the Tutor mailing list