问题:
我需要在long
列表(~600,000个条目)和short
列表(~300,000个条目)之间执行一个有点复杂的交叉引用任务。我试图找到两个列表之间的类似条目,每个唯一条目由三个不同的整数标识(称为int1
,int2
和int3
)。基于一个列表中的三个整数标识符,我想看看那些相同的三个整数是否在另一个列表中,并返回它们是哪些。
尝试:
首先,我将long
列表中的每个三个整数元组压缩成一个名为a
的数组。同样,我将short
列表中的每个三元组元组压缩为一个名为b
的数组:
a = [(int1,int2,int3),...] # 600,000 entries
b = [(int1,int2,int3),...] # 300,000 entries
然后我遍历a
中的每个条目,看看它是否在b
中。如果是,我将相应的元组附加到名为c
的循环外的数组中:
c= []
for i in range(0,len(a),1):
if a[i] in b:
c.append(a[i])
迭代(毫不奇怪)非常缓慢。我猜Python必须在每次迭代时检查b
a[i]
(约300,000次!),并且迭代600,000次。它现在花了一个多小时还没有完成,所以我知道我应该优化一些东西。
我的问题是:执行此交叉引用的最Pythonic或最快的方法是什么?
答案 0 :(得分:9)
您可以使用套装:
c = set(b).intersection(a)
我选择将b
转换为集合,因为它是两个列表中较短的一个。使用intersection()
不需要首先将列表a
转换为集合。
你也可以这样做:
c = set(a) & set(b)
但是,这两个列表都需要首先转换为set
类型。
无论哪种方式都有O(n)操作,请参阅time complexity。
答案 1 :(得分:1)
Pandas
解决方案:
a = [(1,2,3),(4,5,6),(4,5,8),(1,2,8) ]
b = [(1,2,3),(0,3,7),(4,5,8)]
df1 = pd.DataFrame(a)
print (df1)
0 1 2
0 1 2 3
1 4 5 6
2 4 5 8
3 1 2 8
df2 = pd.DataFrame(b)
print (df2)
0 1 2
0 1 2 3
1 0 3 7
2 4 5 8
df = pd.merge(df1, df2)
print (df)
0 1 2
0 1 2 3
1 4 5 8
纯python
解决方案set
s:
c = list(set(b).intersection(set(a)))
print (c)
[(4, 5, 8), (1, 2, 3)]
答案 2 :(得分:0)
另一个有趣的方法:
from itertools import compress
list(compress(b, map(lambda x: x in a, b)))
另一个:
filter(lambda x: x in a, b)