获取两个列表的独特条目差异

1242 投票
33 回答
1507818 浏览
提问于 2025-04-16 02:39

我在Python里有两个列表:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

假设每个列表里的元素都是独一无二的,我想创建一个第三个列表,里面包含第一个列表中那些不在第二个列表里的元素:

temp3 = ['Three', 'Four']

有没有什么快速的方法,不用循环和检查呢?

33 个回答

267

可以使用Python的异或(XOR)运算符来实现。

  • 这样可以去掉每个列表中的重复项。
  • 这会显示temp1和temp2之间的差异,以及temp2和temp1之间的差异。

set(temp1) ^ set(temp2)
648

现有的解决方案要么提供以下两种中的一种:

  • 性能比 O(n*m) 更快。
  • 保持输入列表的顺序。

但到目前为止,没有任何解决方案能同时满足这两点。如果你想要两者兼得,可以试试这个:

s = set(temp2)
temp3 = [x for x in temp1 if x not in s]

性能测试

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print timeit.timeit('list(set(temp1) - set(temp2))', init, number = 100000)
print timeit.timeit('s = set(temp2);[x for x in temp1 if x not in s]', init, number = 100000)
print timeit.timeit('[item for item in temp1 if item not in temp2]', init, number = 100000)

结果:

4.34620224079 # ars' answer
4.2770634955  # This answer
30.7715615392 # matt b's answer

我提出的方法不仅保持了顺序,而且比集合减法稍微快一些,因为它不需要构建一个不必要的集合。如果第一个列表明显比第二个长,而且哈希计算比较耗时,性能差异会更加明显。这里有第二个测试来演示这一点:

init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''

结果:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
1789

如果你想找出在 temp1 中但不在 temp2 中的元素(假设每个列表中的元素都是唯一的),可以这样做:

In [5]: list(set(temp1) - set(temp2))
Out[5]: ['Four', 'Three']

要注意,这个操作是单向的:

In [5]: set([1, 2]) - set([2, 3])
Out[5]: set([1]) 

也就是说,你可能会希望得到 set([1, 3]) 作为结果。如果你确实想要 set([1, 3]) 作为答案,可以使用 set([1, 2]).symmetric_difference(set([2, 3]))

撰写回答