大多数Pythonic方式交叉引用两个列表

时间:2017-09-29 07:29:52

标签: python arrays pandas numpy list-comprehension

问题:

我需要在long列表(~600,000个条目)和short列表(~300,000个条目)之间执行一个有点复杂的交叉引用任务。我试图找到两个列表之间的类似条目,每个唯一条目由三个不同的整数标识(称为int1int2int3)。基于一个列表中的三个整数标识符,我想看看那些相同的三个整数是否在另一个列表中,并返回它们是哪些。

尝试

首先,我将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或最快的方法是什么?

3 个答案:

答案 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)