如果列表项在另一个列表中,如何在保持顺序的同时将列表项移到前面

我有两个示例列表,

vals = ["a", "c", "d", "e", "f", "g"]
xor  = ["c", "g"] 

我想vals根据xor列表对列表进行排序,即,中的值xor应按vals确切顺序排在列表的首位。中存在的其余值vals应保持相同的顺序。

此外,在这些情况下,值xor可能不在,vals只是忽略这些值。而且,在重复的情况下,我只需要一个值。

期望的输出:

vals = ["c", "g", "a", "d", "e", "f"]
# here a, d, e, f are not in xor so we keep them in same order as found in vals.

我的方法:

new_list = []
for x in vals:
    for y in xor:
        if x == y:
            new_list.append(x)
            
for x in vals:
    if x not in xor:
        new_list.append(x)

vals列表目前有大约 80 万个单词或短语。该xor列表有 30 万个单词或短语,但以后可能会增加。有些短语也有点长。解决问题的最有效方法是什么?

回答

构建 indeces 的 order dictxor并将其用作排序键:

order = {n: i for i, n in enumerate(xor)}

sorted(vals, key=lambda x: order.get(x, len(xor)))
# ['c', 'g', 'a', 'd', 'e', 'f']

使用len(vals)作为默认值,确保所有值不是xor会在后面结束。这当然假定,您要的数值xor基于他们的顺序进行排序xor(制作过程O(M+NlogN))。否则你可以更快(O(M+N)):

from operator import contains
from functools import partial
s = set(xor)
result = list(filter(partial(contains, s), vals))
result.extend(v for v in vals if v not in s)

或者以更易读的方式:

s = set(xor)
result = [v for v in vals if v in s]
result += (v for v in vals if v not in s)


以上是如果列表项在另一个列表中,如何在保持顺序的同时将列表项移到前面的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>