我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
我在Python中有两个列表:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
假设每个列表中的元素都是唯一的,我想用第一个列表中的项创建第三个列表,这些项不在第二个列表中:
temp3 = ['Three', 'Four']
有没有没有周期和检查的快速方法?
当前回答
如果你遇到TypeError: unhashable type: 'list',你需要将列表或集转换为元组。
set(map(tuple, list_of_lists1)).symmetric_difference(set(map(tuple, list_of_lists2)))
参见如何比较python中的列表/集列表?
其他回答
试试这个:
temp3 = set(temp1) - set(temp2)
您可以循环遍历第一个列表,对于不在第二个列表中但在第一个列表中的每一项,将其添加到第三个列表中。例句:
temp3 = []
for i in temp1:
if i not in temp2:
temp3.append(i)
print(temp3)
这里有一些简单的、保持顺序的方法来区分两个字符串列表。
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']
如果您真的关注性能,那么使用numpy!
以下是github上的完整笔记本,并对list、numpy和pandas进行了比较。
https://gist.github.com/denfromufa/2821ff59b02e9482be15d27f2bbd4451
现有的解决方案都提供了其中的一个或另一个:
比O(n*m)性能快。 保持输入列表的顺序。
但到目前为止,还没有一种解决方案兼而有之。如果你两者都想要,试试这个:
s = set(temp2)
temp3 = [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)
结果:
4.34620224079 # ars' answer
4.2770634955 # This answer
30.7715615392 # matt b's answer
我提出的方法以及保持顺序也比集合减法(稍微)快,因为它不需要构造一个不必要的集合。如果第一个列表比第二个列表长得多,并且散列代价昂贵,那么性能差异将更加明显。下面是第二个测试:
init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''
结果:
11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer