Skip to content Skip to sidebar Skip to footer

Python 3 List: How Do I Sort [('nj', 81), ('ca', 81), ('dc', 52)] Base On Number And Then Letters?

If my list is [('IL', 36), ('NJ', 81), ('CA', 81), ('DC', 52), ('TX', 39)], how can I sort it so that my result will be [('CA', 81), ('NJ', 81), ('DC', 52), ('TX', 39), ('IL', 36)]

Solution 1:

If you didn't have the convenience of being able to -somefield, then the Pythonic approach would be to do a multi-phase sort that takes advantage of Python's sort being stable.

a = [('IL', 36), ('NJ', 81), ('CA', 81), ('DC', 52), ('TX', 39)]

from operator import itemgetter
a.sort(key=itemgetter(0))
a.sort(key=itemgetter(1), reverse=True)
# [('CA', 81), ('NJ', 81), ('DC', 52), ('TX', 39), ('IL', 36)]

Solution 2:

Pretty straight forward:

your_list.sort(key=lambda e: (-e[1], e[0]))

for example

>>> your_list = [('IL', 36), ('NJ', 81), ('CA', 81), ('DC', 52), ('TX', 39)]
>>> your_list.sort(key=lambda e: (-e[1], e[0]))
>>> your_list
[('CA', 81), ('NJ', 81), ('DC', 52), ('TX', 39), ('IL', 36)]

Note that the above sorts the list in place. If you want to wrap this in a function and not modify the original list, use sorted

defyour_sort(your_list):
    returnsorted(your_list, key=lambda e: (-e[1], e[0]))

Solution 3:

Compare the first element if it is not equal, if equal compare the second element. If you want in reverse order, switch cmp(a, b) for cmp(b, a).

>>> a = [('IL', 36), ('NJ', 81), ('CA', 81), ('DC', 52), ('TX', 39)]
>>> sorted(a, cmp=lambda x, y: 
                      cmp(y[1],x[1]) if x[1]!=y[1] else cmp(x[0],y[0]))
[('CA', 81), ('NJ', 81), ('DC', 52), ('TX', 39), ('IL', 36)]

The other answer is shorter, but this approach works even if one of the elements is not numeric and can be extend for any number of levels, although you may want to write a proper comparison function instead of using lambda - for a generic N-level sort:

>>> defarbitrary_level_tuple_sort(iterable, order=[(0, 'a')]):
        defcomparator(a, b):
            for i, o in order:
                if a[i] != b[i]:
                    if o == 'a':
                        return cmp(a[i], b[i])
                    else:
                        return cmp(b[i], a[i])
            return0returnsorted(iterable, cmp=comparator)

>>> arbitrary_level_tuple_sort(a, [(1, 'd'), (0, 'a')])
[('CA', 81), ('NJ', 81), ('NJ', 81), ('TX', 39), ('IL', 36)]

The order argument is a list of tuple indexes and orders (a=ascending/d=descending), this works for tuples of any size:

>>>b = [tuple([random.randint(0, 10) for i inrange(5)]) for i inrange(5)]>>>b
[(7, 5, 5, 8, 0),
 (0, 4, 5, 0, 7),
 (7, 4, 0, 9, 0),
 (1, 1, 3, 9, 4),
 (6, 2, 9, 6, 3)]

Sort by the 4th element (index 3) descending, then for the 5th and first ascending:

>>>arbitrary_level_tuple_sort(b, [(3, 'd'), (4, 'a'), (0, 'a')])
[(7, 4, 0, 9, 0),
 (1, 1, 3, 9, 4),
 (7, 5, 5, 8, 0),
 (6, 2, 9, 6, 3),
 (0, 4, 5, 0, 7)]

Post a Comment for "Python 3 List: How Do I Sort [('nj', 81), ('ca', 81), ('dc', 52)] Base On Number And Then Letters?"