2012-12-19 159 views
12

我的问题是非常相似,这两个环节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' 来,因为0.8> 0.6 'd' 之前。 'e'在0.4> 0.1之后出现在'a'之前。

任何帮助?

谢谢!

回答

12

我想你应该能够做到这一点:

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项目对这些元素进行排序。然后,我们只需要使用zip和参数解包再次取消List1元素 - 尽管如果您想确保在一天结束时有一个列表而不是元组,那么您可以使用列表理解轻松完成。

如果您不能轻易否定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) 

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

+0

,你需要排序列表2和项目list3,但好您的解决方案一样。 –

+0

@MartijnPieters - 你的也是;-) - 你只是不保留结果。 – mgilson

4

这需要一个装饰排序-去除装饰步骤:

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'] 
+0

如果我们能够弄清楚如何使这个工作成功,如果否定List3中的元素不会导致它按照相反的顺序排序:) - 如果它包含字符串 – mgilson

+0

@mgilson:我认为你可以在两遍中使用并使用'reverse = True',否? – DSM

+0

@DSM - 是的。我知道这将会是什么,但是由于某种原因,我看不到你的评论,直到物流。我已经添加到我的答案。 – mgilson

2
>>> [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'] 
相关问题