我需要比较两个列表,以便创建一个在一个列表中找到而在另一个列表中没有的特定元素的新列表。例如:

main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"] 

我想循环遍历list_1,并将list_2中没有在list_1中找到的所有元素附加到main_list。

结果应该是:

main_list=["f", "m"]

我怎么用python来做呢?


当前回答

我用了两种方法,我发现其中一种方法比另一种更有用。以下是我的回答:

我的输入数据:

crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']

Method1: np。我喜欢这种方法,因为它保留了位置

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']

Method1 np。Setdiff1d完全符合我的要求。 这是信息的答案。

其他回答

如果要考虑出现的次数,则可能需要使用集合之类的方法。计数器:

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[key] != 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[key] != counts]

>>> final
['a', 'f', 'm']

从ser1中删除ser2中的条目。

输入

1 = pd。系列([1、2、3、4、5]) ser2 = pd。系列([4、5、6、7、8])

解决方案

ser1[~ser1.isin(ser2)]

我用了两种方法,我发现其中一种方法比另一种更有用。以下是我的回答:

我的输入数据:

crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']

Method1: np。我喜欢这种方法,因为它保留了位置

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']

Method1 np。Setdiff1d完全符合我的要求。 这是信息的答案。

如果你想要一个一行程序解决方案(忽略导入),对于长度为n和m的输入只需要O(max(n, m))的工作,而不是O(n * m)的工作,你可以使用itertools模块:

from itertools import filterfalse

main_list = list(filterfalse(set(list_1).__contains__, list_2))

这利用了函数函数在构造时接受回调函数的优点,允许它只创建一次回调函数,并为每个元素重用它,而不需要将它存储在某个地方(因为filterfalse将它存储在内部);列表推导式和生成器表达式可以做到这一点,但它很难看

在一行中得到相同的结果:

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的答案,它不涉及临时列表或集(即使集大致为O(1),它们每次检查的“常量”系数比简单的相等检查高),并且涉及O(min(n, m))工作,比任何其他答案都少,如果您的问题是位置敏感的,则当匹配元素出现在不匹配的偏移处时,是唯一正确的解决方案。

†:将列表理解作为单行程序来做同样的事情的方法是滥用嵌套循环来创建和缓存“最外层”循环中的值,例如:

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]

这也给Python 3带来了轻微的性能好处(因为现在set_1在理解代码中是本地范围,而不是每次检查都从嵌套范围中查找;在Python 2上,这并不重要,因为Python 2不使用闭包进行列表推导;它们在相同的范围内运行)。

我将这些列表压缩在一起,逐个元素进行比较。

main_list = [b for a, b in zip(list1, list2) if a!= b]