我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
当前回答
下面是@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()来获得你正在寻找的结果。
其他回答
由于目前的解决方案都不产生一个元组,我将抛出:
temp3 = tuple(set(temp1) - set(temp2))
另外:
#edited using @Mark Byers idea. If you accept this one as answer, just accept his instead.
temp3 = tuple(x for x in temp1 if x not in set(temp2))
像其他在这个方向上得到答案的非元组一样,它保持了顺序
试试这个:
temp3 = set(temp1) - set(temp2)
以下是@SuperNova的回答的修改版本
def get_diff(a: list, b: list) -> list:
return list(set(a) ^ set(b))
这是另一个解决方案:
def diff(a, b):
xa = [i for i in set(a) if i not in b]
xb = [i for i in set(b) if i not in a]
return xa + xb
获取在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(设置([2、3]))。