我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
当前回答
def diffList(list1, list2): # returns the difference between two lists.
if len(list1) > len(list2):
return (list(set(list1) - set(list2)))
else:
return (list(set(list2) - set(list1)))
例如,如果list1 =[10, 15, 20, 25, 30, 35, 40]和list2 =[25, 40, 35],那么返回的列表将输出= [10,20,30,15]
其他回答
下面是@arkolec的回答,下面是一个用于比较列表、元组和集的实用程序类:
from difflib import SequenceMatcher
class ListDiffer:
def __init__(self, left, right, strict:bool=False):
assert isinstance(left, (list, tuple, set)), "left must be list, tuple or set"
assert isinstance(right, (list, tuple, set)), "right must be list, tuple or set"
self.l = list(left) if isinstance(left, (tuple, set)) else left
self.r = list(right) if isinstance(left, (tuple, set)) else right
if strict:
assert isinstance(left, right.__class__), \
f'left type ({left.__class__.__name__}) must equal right type ({right.__class__.__name__})'
self.diffs = []
self.equal = []
for tag, i, j, k, l in SequenceMatcher(None, self.l, self.r).get_opcodes():
if tag in ['delete', 'replace', 'insert']:
self.diffs.append((tag, i, j, k, l))
elif tag == 'equal':
[self.equal.append(v) for v in left[i:j]]
def has_diffs(self):
return len(self.diffs) > 0
def only_left(self):
a = self.l[:]
[a.remove(v) for v in self.equal]
return a
def only_right(self):
a = self.r[:]
[a.remove(v) for v in self.equal]
return a
def __str__(self, verbose:bool=False):
iD = 0
sb = []
if verbose:
sb.append(f"left: {self.l}\n")
sb.append(f"right: {self.r}\n")
sb.append(f"diffs: ")
for tag, i, j, k, l in self.diffs:
s = f"({iD})"
if iD > 0: sb.append(' | ')
if tag in ('delete', 'replace'): s = f'{s} l:{self.l[i:j]}'
if tag in ('insert', 'replace'): s = f'{s} r:{self.r[k:l]}'
sb.append(s)
iD = iD + 1
if verbose:
sb.append(f"\nequal: {self.equal}")
return ''.join(sb)
def __repr__(self) -> str:
return "<ListDiffer> {}".format(self.__str__())
用法:
left = ['a','b','c']
right = ['aa','b','c','d']
# right = ('aa','b','c','d')
ld = ListDiffer(left, right, strict=True)
print(f'ld.has_diffs(): {ld.has_diffs()}')
print(f'ld: {ld}')
print(f'ld.only_left(): {ld.only_left()}')
print(f'ld.only_right(): {ld.only_right()}')
输出:
ld.has_diffs(): True
ld: (0) l:['a'] r:['aa'] | (1) r:['d']
ld.only_left(): ['a']
ld.only_right(): ['aa', 'd']
我不能说性能,但你可以使用ld.only_left()来获得你正在寻找的结果。
如果你遇到TypeError: unhashable type: 'list',你需要将列表或集转换为元组。
set(map(tuple, list_of_lists1)).symmetric_difference(set(map(tuple, list_of_lists2)))
参见如何比较python中的列表/集列表?
可以使用python的XOR运算符来完成。
这将删除每个列表中的重复项 这将显示temp1与temp2和temp2与temp1的差异。
set(temp1) ^ set(temp2)
试试这个:
temp3 = set(temp1) - set(temp2)
这里有一个最简单情况的反答案。
这比上面那个做双向差分的要短,因为它只做了问题要求的事情:生成第一个列表中的东西的列表,而不是第二个列表中的东西。
from collections import Counter
lst1 = ['One', 'Two', 'Three', 'Four']
lst2 = ['One', 'Two']
c1 = Counter(lst1)
c2 = Counter(lst2)
diff = list((c1 - c2).elements())
或者,根据你的可读性偏好,它可以是一个不错的单行代码:
diff = list((Counter(lst1) - Counter(lst2)).elements())
输出:
['Three', 'Four']
请注意,如果您只是对其进行迭代,则可以删除list(…)调用。
因为这个解决方案使用计数器,所以相对于许多基于集合的答案,它可以正确地处理数量。例如,在这个输入中:
lst1 = ['One', 'Two', 'Two', 'Two', 'Three', 'Three', 'Four']
lst2 = ['One', 'Two']
输出结果为:
['Two', 'Two', 'Three', 'Three', 'Four']