Answers:
TL; DR:
解决方案(1)
import numpy as np
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`
解决方案(2) 您需要一个排序列表
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
main_list = setdiff_sorted(list_2,list_1)
说明:
(1)可以使用与NumPy的setdiff1d(array1,array2,assume_unique= False)。
assume_unique询问用户数组是否已经唯一。
如果为False,则首先确定唯一元素。
如果为True,则函数将假定元素已经是唯一的,并且函数将跳过确定唯一元素的操作。
这产生了独特的值array1是不是在array2。assume_unique是False默认。
如果您担心 唯一元素(基于Chinny84的响应),则只需使用(其中assume_unique=False=>默认值):
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)
# yields the elements in `list_2` that are NOT in `list_1`
(2)
对于想要对答案进行排序的人,我做了一个自定义函数:
import numpy as np
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
要获得答案,请运行:
main_list = setdiff_sorted(list_2,list_1)
旁注:
(a)解决方案2(自定义函数setdiff_sorted)返回一个列表(与解决方案1中的数组相比)。
(b)如果不确定这些元素是否唯一,则只需setdiff1d在解决方案A和B中都使用NumPy的默认设置。并发症的例子是什么?见注释(c)。
(c)如果两个列表中的任何一个都不唯一,情况将有所不同。
说list_2的不是唯一的:list2 = ["a", "f", "c", "m", "m"]。保持list1原样:list_1 = ["a", "b", "c", "d", "e"]
设置assume_uniqueyields 的默认值["f", "m"](在两种解决方案中)。但是,如果您设置了assume_unique=True,两种解决方案都可以["f", "m", "m"]。为什么?这是因为用户认为元素是唯一的)。因此,最好保持assume_unique为其默认值。请注意,两个答案均已排序。
您可以使用集:
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']
根据@JonClements的评论,这是一个更简洁的版本:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']
unique元素,那么这很好,但是如果我们有多个元素,那m's该怎么办呢?
list(set(list_2).difference(list_1))来避免显式set转换...
使用这样的列表理解:
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]
list_1,您需要预转换为set/ frozenset,例如set_1 = frozenset(list_1),然后main_list = [item for item in list_2 if item not in set_1]将检查时间从O(n)每个项目减少到(大约)O(1)。
enumerate()它:[index for (index, item) in enumerate(list_2) if item not in list_1]
如果您想要一种单线解决方案(忽略导入),该解决方案仅需要O(max(n, m))长度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]
(因为in list_2中的值与in 中的相同索引相匹配list_1),您绝对应该使用Patrick的答案,该答案不涉及临时lists或sets(即使sets大致相同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=[]
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']
list_1是大,list_2是不平凡的大小,因为它涉及到len(list_2) O(n)的扫描list_1,使它O(n * m)(其中n和m是的长度list_2和list_1分别)。如果您转换list_1成set/ frozenset,则可以在中进行contains的检查O(1),使总工作量O(n)为list_2(技术上为O(max(n, m)),因为您确实O(m)做了set)。
我会将zip这些列表放在一起,以逐个元素比较它们。
main_list = [b for a, b in zip(list1, list2) if a!= b]
lists 的一次廉价传递,并且list正在构造一个新的,而没有其他临时对象,没有昂贵的遏制检查等
我使用了两种方法,发现一种方法比其他方法有用。这是我的答案:
我的输入数据:
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']
方法2:尽管给出的答案与方法1相同,但扰乱了顺序
test = list(set(testmod_mpp).difference(set(crkmod_mpp)))
print(test)
['POA23', 'POA15', 'POA17', 'POA16', 'POA22', 'POA18', 'POA24', 'POA21']
方法1完全np.setdiff1d符合我的要求。此答案仅供参考。
如果应该考虑发生的次数,则可能需要使用类似以下内容的方法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']
list_2没有出现的list_1元素或list_2中没有出现在相同索引处的元素list_1?