27

我正在尝试将两个列表排序在一起:

list1 = [1, 2, 5, 4, 4, 3, 6]
list2 = [3, 2, 1, 2, 1, 7, 8]

list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2))))

无论如何,这样做会给我输出

list1 = [1, 2, 3, 4, 4, 5, 6]
list2 = [3, 2, 7, 1, 2, 1, 8]

虽然我想在第一个列表中保留相等数字 4 的初始顺序:我想要的是

list1 = [1, 2, 3, 4, 4, 5, 6]
list2 = [3, 2, 7, 2, 1, 1, 8]

我需要做什么?我不想使用循环进行冒泡排序。任何帮助表示赞赏。

4

3 回答 3

35

使用key仅比较对的第一个元素的排序参数。由于 Python 的排序是稳定的,这保证了当第一个元素相等时,第二个元素的顺序将保持不变。

>>> from operator import itemgetter
>>> [list(x) for x in zip(*sorted(zip(list1, list2), key=itemgetter(0)))]
[[1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8]]

这相当于:

>>> [list(x) for x in zip(*sorted(zip(list1, list2), key=lambda pair: pair[0]))]
[[1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8]]
于 2012-12-02T10:29:34.843 回答
7

这里的技巧是,当 Python 进行元组比较时,它会按从左到右的顺序比较元素(例如,(4, 1) < (4, 2)这就是在特定情况下您没有得到想要的顺序的原因)。这意味着您需要向函数传递一个key参数sorted,告诉它只使用对元组的第一个元素作为其排序表达式,而不是整个元组。

这可以保证保留您想要的顺序,因为:

保证排序是稳定的。这意味着当多个记录具有相同的键时,它们的原始顺序将被保留。

(资源)

>>> list1 = [1, 2, 5, 4, 4, 3, 6]
>>> list2 = [3, 2, 1, 2, 1, 7, 8]
>>> 
>>> list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2), key=lambda pair: pair[0])))
>>> 
>>> print list1
[1, 2, 3, 4, 4, 5, 6]
>>> print list2
[3, 2, 7, 2, 1, 1, 8]
于 2012-12-02T10:31:11.060 回答
0

在您的代码中,排序是根据元组的第一个和第二个元素执行的,因此生成的第二个列表元素按第一个列表的相同元素的排序顺序排列。

为避免基于第二个列表进行排序,只需指定仅第一个列表中的元素应用于比较元组:

>>> from operator import itemgetter
>>> list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2),key=itemgetter(0))))
>>> list1, list2
([1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8])

itemgetter(0)从每个元组中获取第一个元素,该元素属于第一个列表。

于 2012-12-02T10:33:15.117 回答