My question is very similar to these two links 1 and 2:
我的问题与这两个链接1和2非常相似:
I have three different lists. I want to sort List1 based on List2 (in ascending order). However, I have repeats in List2. I then want to sort these repeats by List3 (in descending order). Confusing enough?
我有三个不同的列表。我想基于List2对List1进行排序(按升序排序)。但是,我在List2中重复了一遍。然后我想按List3对这些重复进行排序(按降序排列)。足够困惑?
What I have:
我拥有的:
List1 = ['a', 'b', 'c', 'd', 'e']
List2 = [4, 2, 3, 2, 4]
List3 = [0.1, 0.8, 0.3, 0.6, 0.4]
What I want:
我想要的是:
new_List1 = ['b', 'd', 'c', 'e', 'a']
'b' comes before 'd' since 0.8 > 0.6. 'e' comes before 'a' since 0.4 > 0.1.
'b'出现在'd'之前,因为0.8> 0.6。 'e'出现在'a'之前,因为0.4> 0.1。
Any help?
有帮助吗?
Thanks!
谢谢!
3 个解决方案
#1
12
I think you should be able to do this by:
我认为你应该能够做到这一点:
paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
l2,l3,l1 = zip(*paired_sorted)
In action:
在行动:
>>> 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')
Here's how it works. First we match corresponding elements from your lists using zip
. We then sort those elements based on the items from List2 first and (negated) List3 second. Then we just need to pull off the List1 elements again using zip
and argument unpacking -- Although you could do it easily with a list-comprehension if you wanted to make sure you had a list at the end of the day instead of a tuple.
这是它的工作原理。首先,我们使用zip匹配您列表中的相应元素。然后,我们首先根据List2中的项目和(否定的)List3秒对这些元素进行排序。然后我们只需要使用zip和参数解包再次拉出List1元素 - 虽然如果你想确保在一天结束时有一个列表而不是一个元组,你可以轻松地使用列表理解。
This gets a little tougher if you can't easily negate the values in List3 -- e.g. if they're strings. You need to do the sorting in 2 passes:
如果你不能轻易否定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)
(you could use operator.itemgetter(1)
in place of lambda x:x[1]
in the above if you prefer). This works because python sorting is "stable". It doesn't re-order "equal" elements.
(如果您愿意,可以使用operator.itemgetter(1)代替上面的lambda x:x [1]。这是有效的,因为python排序是“稳定的”。它没有重新排序“相等”的元素。
#2
4
This requires a decorate-sort-undecorate step:
这需要一个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]
or, combined into one line:
或者,合并成一行:
new_list1 = [v[0] for v in sorted(zip(List1, List2, List3), key=lambda v: (v[1], -v[2]))]
Output:
输出:
>>> 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']
#3
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']
This sorts the index/value pairs by using the indices to get the corresponding values from the other lists to use in the key function used for ordering by sorted()
, and then extracts just the values using a list comprehension.
这通过使用索引来获取索引/值对,以从其他列表中获取相应的值,以在用于按sorted()排序的键函数中使用,然后使用列表推导仅提取值。
Here is a shorter alternative that sorts just the indices and then uses those indices to grab the values from List1
:
这是一个较短的替代方法,只对索引进行排序,然后使用这些索引从List1中获取值:
>>> [List1[i] for i in sorted(range(len(List1)), key=lambda i: (List2[i], -List3[i]))]
['b', 'd', 'c', 'e', 'a']
#1
12
I think you should be able to do this by:
我认为你应该能够做到这一点:
paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
l2,l3,l1 = zip(*paired_sorted)
In action:
在行动:
>>> 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')
Here's how it works. First we match corresponding elements from your lists using zip
. We then sort those elements based on the items from List2 first and (negated) List3 second. Then we just need to pull off the List1 elements again using zip
and argument unpacking -- Although you could do it easily with a list-comprehension if you wanted to make sure you had a list at the end of the day instead of a tuple.
这是它的工作原理。首先,我们使用zip匹配您列表中的相应元素。然后,我们首先根据List2中的项目和(否定的)List3秒对这些元素进行排序。然后我们只需要使用zip和参数解包再次拉出List1元素 - 虽然如果你想确保在一天结束时有一个列表而不是一个元组,你可以轻松地使用列表理解。
This gets a little tougher if you can't easily negate the values in List3 -- e.g. if they're strings. You need to do the sorting in 2 passes:
如果你不能轻易否定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)
(you could use operator.itemgetter(1)
in place of lambda x:x[1]
in the above if you prefer). This works because python sorting is "stable". It doesn't re-order "equal" elements.
(如果您愿意,可以使用operator.itemgetter(1)代替上面的lambda x:x [1]。这是有效的,因为python排序是“稳定的”。它没有重新排序“相等”的元素。
#2
4
This requires a decorate-sort-undecorate step:
这需要一个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]
or, combined into one line:
或者,合并成一行:
new_list1 = [v[0] for v in sorted(zip(List1, List2, List3), key=lambda v: (v[1], -v[2]))]
Output:
输出:
>>> 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']
#3
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']
This sorts the index/value pairs by using the indices to get the corresponding values from the other lists to use in the key function used for ordering by sorted()
, and then extracts just the values using a list comprehension.
这通过使用索引来获取索引/值对,以从其他列表中获取相应的值,以在用于按sorted()排序的键函数中使用,然后使用列表推导仅提取值。
Here is a shorter alternative that sorts just the indices and then uses those indices to grab the values from List1
:
这是一个较短的替代方法,只对索引进行排序,然后使用这些索引从List1中获取值:
>>> [List1[i] for i in sorted(range(len(List1)), key=lambda i: (List2[i], -List3[i]))]
['b', 'd', 'c', 'e', 'a']