13

我的问题与这两个链接12非常相似:

我有三个不同的列表。我想根据 List2 对 List1 进行排序(按升序排列)。但是,我在 List2 中有重复。然后我想按 List3 对这些重复进行排序(按降序排列)。够迷惑吗?

是)我有的:

List1 = ['a', 'b', 'c', 'd', 'e']
List2 = [4, 2, 3, 2, 4]
List3 = [0.1, 0.8, 0.3, 0.6, 0.4]

我想要的是:

new_List1 = ['b', 'd', 'c', 'e', 'a']

'b' 出现在 'd' 之前,因为 0.8 > 0.6。'e' 出现在 'a' 之前,因为 0.4 > 0.1。

4

3 回答 3

13

我认为您应该能够通过以下方式做到这一点:

paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
l2,l3,l1 = zip(*paired_sorted)

在行动:

>>> List1 = ['a', 'b', 'c', 'd', 'e']
>>> List2 = [4, 2, 3, 2, 4]
>>> List3 = [0.1, 0.8, 0.3, 0.6, 0.4]
>>> paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
>>> l2,l3,l1 = zip(*paired_sorted)
>>> print l1
('b', 'd', 'c', 'e', 'a')

这是它的工作原理。首先,我们使用 匹配列表中的相应元素zip。然后,我们首先根据 List2 中的项目和(否定的)List3 中的项目对这些元素进行排序。然后我们只需要使用和参数解包再次拉出 List1 元素zip——尽管如果您想确保在一天结束时有一个列表而不是元组,您可以使用列表理解轻松完成。

如果您不能轻易地否定 List3 中的值——例如,如果它们是字符串,这将变得更加困难。您需要在 2 遍中进行排序:

paired = zip(List2,List3,List1)
rev_sorted = sorted(paired,reverse=True,key=lambda x: x[1])  #"minor" sort first
paired_sorted = sorted(rev_sorted,key=lambda x:x[0])         #"major" sort last
l2,l3,l1 = zip(*paired_sorted)

(如果您愿意,可以使用上面operator.itemgetter(1)的代替lambda x:x[1])。这是有效的,因为 python 排序是“稳定的”。它不会重新排序“相等”的元素。

于 2012-12-19T17:19:09.443 回答
5

这需要一个 decorate-sort-undecorate 步骤:

decorated = zip(List1, List2, List3)
decorated.sort(key=lambda v: (v[1], -v[2]))
new_list1 = [v[0] for v in decorated]

或者,合并为一行:

new_list1 = [v[0] for v in sorted(zip(List1, List2, List3), key=lambda v: (v[1], -v[2]))]

输出:

>>> List1 = ['a', 'b', 'c', 'd', 'e']
>>> List2 = [4, 2, 3, 2, 4]
>>> List3 = [0.1, 0.8, 0.3, 0.6, 0.4]
>>> new_list1 = [v[0] for v in sorted(zip(List1, List2, List3), key=lambda v: (v[1], -v[2]))]
>>> new_list1
['b', 'd', 'c', 'e', 'a']
于 2012-12-19T17:19:26.147 回答
3
>>> [v for i, v in sorted(enumerate(List1), key=lambda i_v: (List2[i_v[0]], -List3[i_v[0]]))]
['b', 'd', 'c', 'e', 'a']

这通过使用索引对索引/值对进行排序,以从其他列表中获取相应的值,以在用于排序的键函数中使用sorted(),然后使用列表推导仅提取值。

这是一个较短的替代方案,它仅对索引进行排序,然后使用这些索引从 中获取值List1

>>> [List1[i] for i in sorted(range(len(List1)), key=lambda i: (List2[i], -List3[i]))]
['b', 'd', 'c', 'e', 'a']
于 2012-12-19T17:20:18.847 回答