如何根据另一个列表对一个列表进行排序?

27
我有两个列表,一个参考列表和一个输入列表。
Ref = [3, 2, 1, 12, 11, 10, 9, 8, 7, 6, 5, 4]
Input = [9, 5, 2, 3, 10, 4, 11, 8]

我希望对输入列表进行排序,使其顺序与参考列表相同。如果在输入列表中缺少某个元素,则可以跳过并进行下一个元素。

因此,根据参考列表排序后的输入列表将是这样的:

Sorted_Input = [3, 2, 11, 10, 9, 8, 5, 4]

2
为什么不循环引用列表并检查项目是否在输入列表中呢? new = [val for val in Ref if val in Input] - Isdj
@Georgy - 上述问题仅保留其他列表中存在的元素,但我还在寻找排序,这就是为什么这是一个不同的问题。 - Hardik Gupta
1
这里没有排序,只有过滤。请参见重复目标中的已接受答案。它与此处的已接受答案相同,并且将产生您想要的相同结果。 - Georgy
@Georgy - 现在我同意你的观点。 - Hardik Gupta
4个回答

25

我认为这回答了你的问题:

>>> [x for x in Ref if x in Input]
>>> [3, 2, 11, 10, 9, 8, 5, 4]

希望它有所帮助。

更新:Input转换为set以实现更快的访问:

>>> Input_Set = set(Input)
>>> [x for x in Ref if x in Input_Set]
[3, 2, 11, 10, 9, 8, 5, 4]

3
可能对问题提出者来说这并不重要,因为他们已经接受了答案,但需要注意的是这个方法会去除重复项并对其进行排序,例如,[1, 1, 1, 3] 会被转换成 [3, 1] - Steve Jessop
@SteveJessop 我知道,某个时候OP说“Input”的元素都是不同的。现在我很困惑,我以为这个答案有几条评论关于这个问题。 - dcg
@SteveJessop - 我的输入和引用永远不会有重复,所以是的,这个解决方案总是有效的。 - Hardik Gupta

8

除了dcg的回答外,另一种方法如下:

Ref = [3, 2, 1, 12, 11, 10, 9, 8, 7, 6, 5, 4]
Input = [9, 5, 2, 3, 10, 4, 11, 8]

ref = set(Ref)
inp = set(Input)

sorted_list = sorted(ref.intersection(inp), key = Ref.index)

这会输出为:
[3, 2, 11, 10, 9, 8, 5, 4]

在这里,您将把列表转换为集合,找到它们的交集并进行排序。根据“Ref”列表的索引,对集合进行排序。

8
你可以使用sorted方法:
# keep in a dict the index for each value from Ref
ref  = {val: i for i, val in enumerate(Ref)}
# sort by the index value from Ref for each number from Input 
sorted(Input, key=ref.get)

输出:

[3, 2, 11, 10, 9, 8, 5, 4]

6

以下是朴素的方法:

sorted(Input, key=Ref.index)

或者原地修改:

Input.sort(key=Ref.index)

无论哪种方式,这只是一行代码。

虽然我认为它很慢——O(n*m),其中n和m是输入(Input)参考(Ref)的长度。 @rusu_ro1的解决方案使用类似的方法,但似乎是O(n+m)。


2
从技术上讲,我想除非我们知道输入数据足够大以至于速度很重要,否则任何其他解决方案都是过早优化。 - JollyJoker
1
@JollyJoker 非常正确,谢谢提醒。 - wjandrea
2
@JollyJoker 而且不知道实际列表中有哪些元素(重复/唯一元素,可哈希或不可哈希等)。 - Graipher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接