# sorting the list by inner elements

John Hunter jdhunter at ace.bsd.uchicago.edu
Thu Mar 25 14:31:16 CET 2004

>>>>> "ketulp" == ketulp baroda <ketulp_baroda at yahoo.com> writes:

ketulp> I like ur idea but this will work for only when inner list
ketulp> has only two elements. if inner list has five elements and
ketulp> i want to sort the whole list by 3rd element then how can
ketulp> i do this ?

The general approach is to arrange the elements in the order you want
them sorted, sort them, and then revert to original order.  So if you
have 5 elements, and you want them sorted by the 3rd, put the 3rd
first.  If any two of the first elements are the same, the second
element of the list will break the tie, and so on.

Supposing you want to sort by the 3rd element, and you don't care
about the relative order of the other fields

# swap the first an 3rd elements
tmp = [ (e[2], e[1], e[0], e[3], e[4]) for e in seq]
tmp.sort()
# swap them back
seq = [ (e[2], e[1], e[0], e[3], e[4]) for e in tmp]

If you care about performance, you might want to test this against a
custom comparison func passed to sort.  My guess is that this will
win.

You can generalize this to N tuples where you want to filly specify
the sort order.  If memory is not a problem, it's easiest to create a
new list of 2 tuples.  The first element of the list is your reordered
N tuple, the second element of the list is your original N tuple which
you save and extract after the sort.

seq = [(1,2,3,4,9), (-1,-2,2,4,1), (12, 3, -1, 0,12)]
order = 3,2,0,1,4

ordered = [ [ e[ind] for ind in order] for e in seq]
tmp = zip(ordered, seq)
tmp.sort()
seq = [ seq for ordered, seq in tmp]

If memory is an issue and you don't want to create a duplicate of your
entire list in memory, you can work out the indexes to restore the
original tuple order.

JDH