在Python中查找和删除两个列表中的匹配项

时间:2017-03-05 20:39:23

标签: python list-comprehension

所以我有两个int列表xs和ys(任意长度),并希望有效地删除每个列表中出现的重复项。由于您无法在循环播放列表时编辑列表,因此我的尝试是:

matches = [match for match in xs if match in ys]
for match in matches: 
    xs.remove(match)
    ys.remove(match)

但重要的是,如果值在xs中出现两次但在ys中出现一次,则会产生错误,因为"如果匹配在ys"对于相同的值,求值为true两次,但我需要它只计算一次。

所以澄清,如果:

xs = [0, 2, 4, 8, 8, 100]
ys = [1, 3, 5, 8, 8, 8, 10]

然后需要从两个列表中删除8次。

我该如何有效地做到这一点?感谢

编辑:列表不一定是有序的,实际上两个列表都可能包含重复项。

1 个答案:

答案 0 :(得分:4)

您可以使用多重集(collections.Counter)作为交集。如果您期望大量重复项并且列表很大,则建议避免使用.remove,因为它很昂贵。列表理解能够更好地扩展。我们使用一些适度的itertools技巧来过滤掉标记的重复项。请注意,这可以调整,例如,不删除第一个,而是删除最后一次等。

from collections import Counter
from itertools import repeat, chain

xc = Counter(xs)
yc = Counter(ys)
matches = xc & yc
tr = repeat(True)
rm = {k: chain(repeat(False, m), tr) for k, m in matches.items()}
xs = [x for x in xs if not x in rm or next(rm[x])]
rm = {k: chain(repeat(False, m), tr) for k, m in matches.items()}
ys = [y for y in ys if not y in rm or next(rm[y])]

请注意,这仅适用于您的元素是可以清除的。