获取两个列表之间的不同项,这些项是唯一的。

1230

我在Python中有两个列表:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

假设每个列表中的元素都是唯一的,我希望创建第三个列表,其中包含第一个列表中不在第二个列表中的项目:

假设每个列表中的元素都是唯一的,我想要创建一个新的列表,其中包含来自第一个列表的但不在第二个列表中的项目:

temp3 = ['Three', 'Four']

有没有不需要循环和检查的快速方式?


26
元素是否保证唯一?如果你有 temp1 = ['One', 'One', 'One']temp2 = ['One'],你希望得到 ['One', 'One'] 还是 [] - Michael Mrozek
1
@michael-mrozek 他们是独一无二的。 - Max Frai
19
你想保留元素的顺序吗? - Mark Byers
1
这个回答解决了您的问题吗?查找不在列表中的元素 - Gonçalo Peres
33个回答

-1
最快的选择是所有可能选项中的一个。
s = set(temp2);
[x for x in temp1 if x not in s]

表现结果

    import timeit
    init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
    print(timeit.timeit('list(set(temp1) - set(temp2))', init, number = 100000))
    print(timeit.timeit('s = set(temp2);[x for x in temp1 if x not in s]', init, number = 100000))
    print(timeit.timeit('[item for item in temp1 if item not in temp2]', init, number = 100000))
    print(timeit.timeit('list(set(temp1) ^ set(temp2))', init, number = 100000))

结果

0.3485999000258744
0.3314229999668896
2.067719299986493
0.3791518000070937

-2
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],则返回的列表将是output = [10, 20, 30, 15]

你不能在差异操作中这样做。 即使是整数,如果你让一个函数执行“a-b”,它应该只从'a'中减去'b',无论'b'是否大于'a'。列表和集合也是如此。A - B和B - A都可以是有效的操作,而不管A和B的长度,你只需要从A中排除B的内容以执行A - B。 - Abu Talha Danish

-3

继@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()来获得您想要的结果。


为什么会有这么多的踩? - jtlz2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接