我需要比较两个列表,以便创建在一个列表中找到但在另一个列表中找不到的特定元素的新列表。例如:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
我想遍历list_1并向list_list追加list_2中找不到list_1中的所有元素。
结果应为:
main_list=["f", "m"]
我怎样才能用python做到这一点?
答案 0 :(得分:86)
您可以使用套装:
main_list = list(set(list_2) - set(list_1))
输出:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']
Per @JonClements'的评论,这是一个更整洁的版本:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']
答案 1 :(得分:36)
(1)你可以使用NumPy的setdiff1d
。从response of Chinny84开始,如果您关注唯一元素,那么:
import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"]
main_list = np.setdiff1d(list_2,list_1)
(2)否则,请使用main_list = np.setdiff1d(list_2,list_1, assume_unique=True)
这两个答案都会给你["f", "m"]
。但是,如果list_2 = ["a", "f", "c", "m", "m"]
,则答案(1)产生["f", "m"]
但答案(2)给出["f", "m", "m"]
(因为list_2
中每个元素的唯一性并不重要)。
答案 2 :(得分:33)
当您使用原生方法时,不确定为什么上述解释如此复杂:
main_list = list(set(list_2)-set(list_1))
答案 3 :(得分:18)
像这样使用list comprehension:
main_list = [item for item in list_2 if item not in list_1]
<强>输出:强>
>>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"]
>>>
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']
修改强>
如下面的评论所述,对于大型列表,上述内容并非理想的解决方案。在这种情况下,更好的选择是首先将list_1
转换为set
:
set_1 = set(list_1) # this reduces the lookup time from O(n) to O(1)
main_list = [item for item in list_2 if item not in set_1]
答案 4 :(得分:4)
如果您想要一个单行解决方案(忽略导入),只需要O(max(n, m))
适用于长度为n
和m
的输入,而不是O(n * m)
,则可以使用the itertools
module执行此操作:
from itertools import filterfalse
main_list = list(filterfalse(set(list_1).__contains__, list_2))
这利用了在构造上采用回调函数的函数函数,允许它创建一次回调并为每个元素重用它而无需将其存储在某处(因为filterfalse
在内部存储它); list comprehensions和generator表达式可以做到这一点,但它很难看。†
在一行中获得相同的结果:
main_list = [x for x in list_2 if x not in list_1]
速度:
set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]
当然,如果比较是为了定位,那么:
list_1 = [1, 2, 3]
list_2 = [2, 3, 4]
应该产生:
main_list = [2, 3, 4]
(因为list_2
中的值与list_1
中的相同索引匹配),您绝对应该使用Patrick's answer,这不涉及临时list
或{ {1}} s(即使set
s大致为set
,它们每次检查的常数和#34因子都比简单的相等检查更高,并涉及O(1)
个工作,如果您的问题是位置敏感的,那么当匹配元素出现在不匹配的偏移处时,它是唯一正确的解决方案。
†:使用列表推导作为单行做同样事情的方法是滥用嵌套循环来创建和缓存&#34;最外层&#34;循环,例如:
O(min(n, m))
这也为Python 3带来了一些小的性能优势(因为现在main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]
在理解代码中是本地范围的,而不是从每个检查的嵌套范围中查找;在Python 2上并不重要,因为Python 2没有使用闭包进行列表推导;它们的操作范围与它们在其中使用的相同。
答案 5 :(得分:3)
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
for i in list_2:
if i not in list_1:
main_list.append(i)
print(main_list)
输出:
['f', 'm']
答案 6 :(得分:1)
我会将zip
列表一起逐个元素地进行比较。
main_list = [b for a, b in zip(list1, list2) if a!= b]
答案 7 :(得分:0)
如果应考虑出现次数,您可能需要使用collections.Counter
之类的内容:
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
from collections import Counter
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['f', 'm']
正如所承诺的,这也可以处理不同数量的“差异”:
list_1=["a", "b", "c", "d", "e", 'a']
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['a', 'f', 'm']
答案 8 :(得分:0)
从ser1中删除ser2中存在的项目。
ser1 = pd.Series([1、2、3、4、5]) ser2 = pd.Series([4,5,6,7,8])
ser1 [〜ser1.isin(ser2)]
答案 9 :(得分:0)
我使用了两种方法,发现一种方法比其他方法有用。这是我的答案:
我的输入数据:
crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']
方法1:np.setdiff1d
我喜欢这种方法,因为它保留了位置
test= list(np.setdiff1d(testmod_mpp,crkmod_mpp))
print(test)
['M15', 'M16', 'M22', 'M23', 'M20', 'M14', 'M17', 'M21']
Method2:尽管它给出了与Method1相同的答案,但扰乱了顺序
test = list(set(testmod_mpp).difference(set(crkmod_mpp)))
print(test)
['POA23', 'POA15', 'POA17', 'POA16', 'POA22', 'POA18', 'POA24', 'POA21']
方法1 np.setdiff1d
完全符合我的要求。
此答案仅供参考。