如何根据另一个列表中元组的元素顺序对元组列表进行排序?

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

我想重新排序列表list_2,使得每个元组的第一个元素按照list_1指定的顺序排列,因此:

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

我试图使用map函数将filter映射到list_1作为可迭代对象(一般思路是:map(filter(lambda x,j : x[0]==j, list_2),list_1))。但显然它不起作用(我认为是由于类型错误)。如何在最少的代码行数中实现此操作?


2
“我想重新排序” 好的,您想使用内置的 sorted 函数。"按指定顺序跟随" 好的,您可以使用 sorted 函数的 key 参数。"通过列表1来" 即通过其在列表1中的位置,该位置由该列表上的 .index 方法给出。阅读文档,解决方案就呼之欲出了。“我尝试使用map函数将filter映射到list_1上作为可迭代对象” 这没有任何意义。filter 用于删除元素,而不是重新排序它们;并且它已经处理了整个序列。map 用于将单个元素函数 应用于序列。 - Karl Knechtel
这个回答解决了你的问题吗?根据另一个列表的顺序重新排列列表。唯一的区别是你需要获取第一个元组元素:key=lambda t: <function>(t[0]) - wjandrea
[list_2[i-1] for i in list_1] ??? - juanpa.arrivillaga
5个回答

4
制作一个字典来映射您的排序顺序(键为您的数字,值为list_1中的顺序),并使用具有自定义键的sorted函数,该键将第一个项映射到字典中(因此按预期顺序排序):
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')))

输出:

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

注意:我使用了 order.get,并将 float('inf') 作为第二个参数来处理第一项不在 order 中的情况。在这种情况下,元组将会被放在末尾进行排序。如果你使用 -1 作为默认值,这将把未知的键放在开头进行排序


3

以下是实现两步得到所需结果的一种方法:

(i) 创建字典dic1,以查找list1中每个项目的位置。

(ii) 使用字典dic1,根据在list1中的位置,按照第一个元素对list_2进行排序。

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)

输出:

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

3
如果您希望用最少的代码行数实现,可以这样做:
>>> 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)]

这里还有其他解决方案涉及创建字典,对于大型列表更有效率(因为那个index调用的时间复杂度是O(n),这将把排序的时间复杂度从O(n log n)提升到O(n^2)),但对于小型列表,差异可能是微不足道的。


2
你需要的key比其他答案中表示的还要简单。 list1.index(a)告诉你alist1中的位置,如果适用的话。你想根据list1.index(x[0])来排序在list2中找到的x,也就是说,按照x[0]list1中的位置进行排序(我们所有的x[0]值确实都在list1中,所以没有潜在的异常);x是一个lambda参数(即我们在上一句中用来解释规则的名称),因此我们有key=lambda x: list1.index(x[0]);我们想用这个keylist2进行.sort,所以我们直接写出它:
list_2.sort(key=lambda x: list1.index(x[0]))

不需要再构建其他东西。

字典允许在列表上进行一次遍历(好吧,算上字典创建也有两次),而您的方法基本上是o(n**2)(对于其中每个项目迭代列表...)。 - Tomerikoo
不是的;我在这里假设list1是一个常量长度(且较小)的列表,列出了x[0]值的所有可能性,并且这个列表不会因为更大的list2而增加。 - Karl Knechtel
好的,那仍然在技术上是 O(n*m),其中 nm 是列表的大小。有趣的是测量实际影响是什么... - Tomerikoo

0
你可以在Python中向列表的sort函数传递一个"key"函数。这将决定排序后列表的顺序!
list_2.sort(key=lambda x: list_1.index(x[0]))
print(list_2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接