简体   繁体   中英

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

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?

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

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)]

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.

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 x s found in your list2 according to (ie, key ed by) the position of x[0] within list1 , ie, 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 (ie, 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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM