Home > Blockchain >  How to sort a list of tuples according to the order of a tuple element in another list?
How to sort a list of tuples according to the order of a tuple element in another list?

Time:12-23

list_1 = [2, 7, 4, 5, 6, 1, 3, 8, 9]
list_2 = [(1, 5), (2, 0), (3, 6), (4, 4), (5, 3), (6, 2), (7, 1), (8, 7), (9, 8)]

I want to reorder list list_2 such that the first element of each tuple follows the order specified by list_1, so:

list_2_ordered = [(2, 0), (7, 1), (4, 4), (5, 3), (6, 2), (1, 5), (3, 6), (8, 7), (9, 8)]

I try to use the map function to map filter over the list_1 as iterables (the general idea map(filter(lambda x,j : x[0]==j, list_2),list_1). But of course it doesn't work (I think due to type error). How can I do this with the least number of code lines?

CodePudding user response:

Craft a dictionary to map your sorting order (the key being your number and the value the order in list_1) and use sorted with a custom key that will map the first item to the dictionary (and thus the expected order):

order = {k:v for v,k in enumerate(list_1)}
list_2_ordered = sorted(list_2, key=lambda x: order.get(x[0], float('inf')))

Output:

[(2, 0), (7, 1), (4, 4), (5, 3), (6, 2), (1, 5), (3, 6), (8, 7), (9, 8)]

NB. I used order.get with float('inf') as second parameter to handle the case where the first item is not present in order. In this case, the tuple will be sorted at the end. If you use -1 as default value, this will sort the unknown keys at the beginning

CodePudding user response:

Here's one way to get your desired outcome in two steps:

(i) Create dictionary dic1 to lookup the position of each item in list1

(ii) Sort list_2 by the first elements using their positions in list_1 with dictionary dic1

dic1 = {k:v for k,v in zip(list_1, range(len(list_1)))}
list_2.sort(key = lambda x: dic1[x[0]])
print(list_2)

Output:

[(2, 0), (7, 1), (4, 4), (5, 3), (6, 2), (1, 5), (3, 6), (8, 7), (9, 8)]

CodePudding user response:

If you want to do it in the fewest lines of code:

>>> list_2.sort(key=lambda t: list_1.index(t[0]))
>>> list_2
[(2, 0), (7, 1), (4, 4), (5, 3), (6, 2), (1, 5), (3, 6), (8, 7), (9, 8)]

Other solutions here that involve creating a dict are more efficient for large lists (that index call is O(n) so it takes the sort from O(n log n) to O(n^2)), but for a small list like this, the difference is likely to be negligible.

CodePudding user response:

The key you need is even simpler than represented by the other answers.

list1.index(a) tells you the position of a within list1, if applicable. You want to sort the xs found in your list2 according to (i.e., keyed by) the position of x[0] within list1, i.e., according to list1.index(x[0]) (and all of our x[0] values are indeed in list1, so there is no potential exception); x is a lambda parameter (i.e., a name that we used in the previous sentence in order to explain the rule), so we have our key=lambda x: list1.index(x[0]); we want to .sort our list2 with that key, so we write it directly:

list_2.sort(key=lambda x: list1.index(x[0]))

No need to build anything else.

CodePudding user response:

You can pass a "key" function to the lists sort function in python. This determines the order of the sorted list!

list_2.sort(key=lambda x: list_1.index(x[0]))
print(list_2)
  • Related