How to Sort a List/Tuple of Lists/Tuples by the Element At a Given Index

How to sort a list/tuple of lists/tuples by the element at a given index?

sorted_by_second = sorted(data, key=lambda tup: tup[1])

or:

data.sort(key=lambda tup: tup[1])  # sorts in place

The default sort mode is ascending. To sort in descending order use the option reverse=True:

sorted_by_second = sorted(data, key=lambda tup: tup[1], reverse=True)

or:

data.sort(key=lambda tup: tup[1], reverse=True)  # sorts in place

Sort a list of tuples by 2nd item (integer value)

Try using the key keyword with sorted().

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], 
key=lambda x: x[1])

key should be a function that identifies how to retrieve the comparable element from your data structure. In your case, it is the second element of the tuple, so we access [1].

For optimization, see jamylak's response using itemgetter(1), which is essentially a faster version of lambda x: x[1].

How to sort a list of tuples, by the second tuple element?

You can use sorted method with a lambda function as below.

lst=[('TIPE_ORG', 'Corea'), ('TIPE_ORG', 'United Kingdom'), ('TIPE_ORG', 'Russia'), ('TIPE_ORG', 'Germany'),('TIPE_PER', 'Pepe Martínez')]

sorted(lst,key=lambda key:len((key[1])),reverse=True)

Output will be

[('TIPE_ORG', 'United Kingdom'),
('TIPE_PER', 'Pepe Martínez'),
('TIPE_ORG', 'Germany'),
('TIPE_ORG', 'Russia'),
('TIPE_ORG', 'Corea')]

Sort list of lists with tuples by first value

Your second attempt is close, you just need to sort each sublist.

for chunk in distancechunks:
chunk.sort(key=lambda x: x[0])

I'm not sure why you're trying to convert to int when you already have floats.

How to sort a tuple list in python

a = [("label 1", 5), ("label 2", 1), ("label 3", 3), ("label 4", 6)]
a = sorted(a, key = lambda x: int(x[1]), reverse = True)

a becomes

[('label 4', 6), ('label 1', 5), ('label 3', 3), ('label 2', 1)]

Sort tuple list with another list

Algorithm

You can distribute the tuples in a dict of lists according to the second element and iterate over order indices to get the sorted list:

from collections import defaultdict
to_order = [(0, 1), (1, 3), (2, 2), (3, 2)]
order = [2, 1, 3]

bins = defaultdict(list)

for pair in to_order:
bins[pair[1]].append(pair)

print(bins)
# defaultdict(<class 'list'>, {1: [(0, 1)], 3: [(1, 3)], 2: [(2, 2), (3, 2)]})

print([pair for i in order for pair in bins[i]])
# [(2, 2), (3, 2), (0, 1), (1, 3)]

sort or index aren't needed and the output is stable.

This algorithm is similar to the mapping mentioned in the supposed duplicate. This linked answer only works if to_order and order have the same lengths, which isn't the case in OP's question.

Performance

This algorithm iterates twice over each element of to_order. The complexity is O(n). @alfasin's first algorithm is much slower (O(n * m * log n)), but his second one is also O(n).

Here's a list with 10000 random pairs between 0 and 1000. We extract the unique second elements and shuffle them in order to define order:

from random import randrange, shuffle
from collections import defaultdict
from timeit import timeit
from itertools import chain

N = 1000
to_order = [(randrange(N), randrange(N)) for _ in range(10*N)]
order = list(set(pair[1] for pair in to_order))
shuffle(order)


def eric(to_order, order):
bins = defaultdict(list)
for pair in to_order:
bins[pair[1]].append(pair)
return list(chain.from_iterable(bins[i] for i in order))


def alfasin1(to_order, order):
arr = [[] for i in range(len(order))]
d = {k:v for v, k in enumerate(order)}
for item in to_order:
arr[d[item[1]]].append(item)
return [item for sublist in arr for item in sublist]

def alfasin2(to_order, order):
return sorted(to_order, key=lambda item: order.index(item[1]))

print(eric(to_order, order) == alfasin1(to_order, order))
# True
print(eric(to_order, order) == alfasin2(to_order, order))
# True

print("eric", timeit("eric(to_order, order)", globals=globals(), number=100))
# eric 0.3117517130003762
print("alfasin1", timeit("alfasin1(to_order, order)", globals=globals(), number=100))
# alfasin1 0.36100843100030033
print("alfasin2", timeit("alfasin2(to_order, order)", globals=globals(), number=100))
# alfasin2 15.031453827000405


Related Topics



Leave a reply



Submit