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

Posted

技术标签:

【中文标题】如何根据另一个列表中元组元素的顺序对元组列表进行排序?【英文标题】:How to sort a list of tuples according to the order of a tuple element in another list? 【发布时间】:2022-01-24 02:22:01 【问题描述】:
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)。但它当然不起作用(我认为是由于类型错误)。如何我可以用最少的代码行吗?

【问题讨论】:

"我想重新排序" 好的,所以你想要内置的sorted。 “遵循指定的顺序” 好的,所以您使用 key 参数来表示 sorted。 ` by list 1 so` 即,通过它在列表 1 中的 位置,由该列表上的 .index 方法给出。阅读文档,解决方案就退出了。 “我尝试使用 map 函数将 list_1 上的过滤器映射为可迭代对象”这没有任何意义filter 用于删除东西,而不是重新排序;它已经处理了整个序列。 map 用于将单元素函数应用于序列。 这能回答你的问题吗? Rearranging list based on order of another list。唯一的区别是您需要获取第一个元组元素:key=lambda t: <function>(t[0]) [list_2[i-1] for i in list_1]??? 【参考方案1】:

制作一个字典来映射您的排序顺序(键是您的数字,值是 list_1 中的顺序)并使用 sorted 和自定义 key 将第一项映射到字典(因此预期顺序):

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.getfloat('inf') 作为第二个参数来处理order 中不存在第一项的情况。在这种情况下,元组将在最后进行排序。如果您使用-1 作为默认值,这将在开头对未知键进行排序

【讨论】:

【参考方案2】:

这是通过两个步骤获得所需结果的一种方法:

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

(ii) 使用它们在list_1 中的位置和字典dic1,按第一个元素对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)]

【讨论】:

最好使用dic1.get 以避免在缺少值的情况下出错。否则我们得到几乎相同的方法;) +1 是的。也应该使用枚举。我已经比我更喜欢你的答案了 :-) 但是如果我编辑我的答案,它会和你的完全一样,所以我会保持原样。【参考方案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) 的排序),但是对于这样的小列表,差异可能可以忽略不计。

【讨论】:

【参考方案4】:

您需要的key 比其他答案所表示的还要简单。

list1.index(a) 告诉您alist1 中的位置(如果适用)。您想根据x[0]list1 中的位置(即keyed by),即根据list1.index(x[0])(以及我们所有的@ 987654331@的值确实是in list1,所以没有潜在的异常); x 是一个lambda 参数(即,我们在上一句中用于​​解释规则的名称),所以我们有我们的key=lambda x: list1.index(x[0]);我们想.sort我们的list2和那个key,所以我们直接写:

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

无需构建其他任何东西。

【讨论】:

字典允许对列表进行一次传递(确定两次计算 dict 创建),而您的方法基本上是o(n**2)(迭代列表中的每个项目...) 否;我在这里假设list1 是一个恒定长度(并且很小)的列表,它列举了x[0] 值的所有可能性,并且对于更大的list2,这不会增加。 很公平。从技术上讲,这仍然是O(n*m),其中nm 是列表的大小。衡量实际影响是什么会很有趣......【参考方案5】:

您可以将“key”函数传递给 python 中的列表排序函数。这决定了排序列表的顺序!

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

【讨论】:

以上是关于如何根据另一个列表中元组元素的顺序对元组列表进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

根据元组的值,以不同的顺序对元组列表进行排序。

如何按两个元素对元组列表进行排序?

如何根据某些文本标准对元组列表进行分组/存储?

按元组的第二个元素对元组列表进行排序,无需高阶函数或递归

根据元组的值对元组列表中的重复元组进行平均

获取包含元组的列表的索引,其中元组的第一个元素与模式匹配