我在Python中有两个列表:

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

假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:

temp3 = ['Three', 'Four']

有没有没有周期和检查的快速方法?


当前回答

我在这个游戏中有点晚了,但你可以做一个性能的比较,上面提到的一些代码和这个,两个最快的竞争者是,

list(set(x).symmetric_difference(set(y)))
list(set(x) ^ set(y))

我为我的初级编码水平道歉。

import time
import random
from itertools import filterfalse

# 1 - performance (time taken)
# 2 - correctness (answer - 1,4,5,6)
# set performance
performance = 1
numberoftests = 7

def answer(x,y,z):
    if z == 0:
        start = time.clock()
        lists = (str(list(set(x)-set(y))+list(set(y)-set(y))))
        times = ("1 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 1:
        start = time.clock()
        lists = (str(list(set(x).symmetric_difference(set(y)))))
        times = ("2 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 2:
        start = time.clock()
        lists = (str(list(set(x) ^ set(y))))
        times = ("3 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 3:
        start = time.clock()
        lists = (filterfalse(set(y).__contains__, x))
        times = ("4 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 4:
        start = time.clock()
        lists = (tuple(set(x) - set(y)))
        times = ("5 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 5:
        start = time.clock()
        lists = ([tt for tt in x if tt not in y])
        times = ("6 = " + str(time.clock() - start))
        return (lists,times)

    else:    
        start = time.clock()
        Xarray = [iDa for iDa in x if iDa not in y]
        Yarray = [iDb for iDb in y if iDb not in x]
        lists = (str(Xarray + Yarray))
        times = ("7 = " + str(time.clock() - start))
        return (lists,times)

n = numberoftests

if performance == 2:
    a = [1,2,3,4,5]
    b = [3,2,6]
    for c in range(0,n):
        d = answer(a,b,c)
        print(d[0])

elif performance == 1:
    for tests in range(0,10):
        print("Test Number" + str(tests + 1))
        a = random.sample(range(1, 900000), 9999)
        b = random.sample(range(1, 900000), 9999)
        for c in range(0,n):
            #if c not in (1,4,5,6):
            d = answer(a,b,c)
            print(d[1])

其他回答

试试这个:

temp3 = set(temp1) - set(temp2)

我更喜欢使用转换到集,然后使用“差分()”函数。完整的代码是:

temp1 = ['One', 'Two', 'Three', 'Four'  ]                   
temp2 = ['One', 'Two']
set1 = set(temp1)
set2 = set(temp2)
set3 = set1.difference(set2)
temp3 = list(set3)
print(temp3)

输出:

>>>print(temp3)
['Three', 'Four']

这是最容易理解的,而且在将来,如果你处理大型数据,将其转换为集合将删除不需要的重复项。希望能有所帮助;-)

假设我们有两个列表

list1 = [1, 3, 5, 7, 9]
list2 = [1, 2, 3, 4, 5]

从上面两个列表中我们可以看到,list2中有第1、3、5项,而第7、9项不存在。另一方面,第1、3、5项在list1中存在,第2、4项不存在。

返回包含项目7,9和2,4的新列表的最佳解决方案是什么?

以上所有答案都找到了解,现在什么是最优的?

def difference(list1, list2):
    new_list = []
    for i in list1:
        if i not in list2:
            new_list.append(i)

    for j in list2:
        if j not in list1:
            new_list.append(j)
    return new_list

def sym_diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))

利用时间,我们可以看到结果

t1 = timeit.Timer("difference(list1, list2)", "from __main__ import difference, 
list1, list2")
t2 = timeit.Timer("sym_diff(list1, list2)", "from __main__ import sym_diff, 
list1, list2")

print('Using two for loops', t1.timeit(number=100000), 'Milliseconds')
print('Using two for loops', t2.timeit(number=100000), 'Milliseconds')

返回

[7, 9, 2, 4]
Using two for loops 0.11572412995155901 Milliseconds
Using symmetric_difference 0.11285737506113946 Milliseconds

Process finished with exit code 0

下面是@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()来获得你正在寻找的结果。

这里有一些简单的、保持顺序的方法来区分两个字符串列表。

Code

使用pathlib的一个不寻常的方法:

import pathlib


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

p = pathlib.Path(*temp1)
r = p.relative_to(*temp2)
list(r.parts)
# ['Three', 'Four']

这假设两个列表包含相同开头的字符串。更多细节请参阅文档。注意,与set操作相比,它不是特别快。


使用itertools.zip_longest的直接实现:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']