从列表中的子列表中查找公共元素

find common elements from sublist in list

我有两个列表,我必须从第一个列表中提取项目,第一个元素出现在第二个列表中。我粘贴在下面的代码运行良好,但由于我要处理数百万条记录,所以速度非常慢。有人知道如何优化它吗?

a = [[1,0],[2,0],[3,0],[4,0]]
b = [2,4,7,8]

same_nums = list(set([x[0] for x in a]).intersection(set(b)))

result = []

for i in a:
    if i[0] in same_nums:
        result.append(i)

print(result)

尝试使用过滤器来理解列表,而不是创建第二个具有相同大小的列表并通过集合,例如:

[x for x in a if x[0] in b]

可能会更快。

在您发布的代码中,您做了很多事情:创建一个删除第二维的副本,从中创建一个集合,将其与另一个集合相交,然后将该集合复制回列表.大名单至少这样处理了四次。我的提案只通过列表一次,所以我实际上希望它更快。

你把事情复杂化了。只需将 b 变成 set 即可加快包含检查。那么推导式中 a 的一次迭代就足够了:

set_b = set(b)  # makes   vvvvvvvvvvvvv  O(1)
result = [x for x in a if x[0] in set_b]

特别是将 same_nums 变回 list 是真正的性能杀手,因为它使整个事情再次 O(m*n)b 中的一组是 O(m+n)。但是 same_nums 一开始是完全没有必要的,因为你知道所有 i[0] 都在 a 中,因为你正在迭代 a.

我推荐使用 Numpy 库,因为它在后台使用 C/C++ 实现,因此运行速度更快。

import numpy as np

a = np.random.randint(10000, size=(10000000, 2))
b = np.random.randint(10000, size=1000)

mask = np.isin(a[:,0], b)
a_masked = a[mask, :]

# Exec time: 3.2 s ± 185 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

另一种方法(Python 列表)相同数量元素的执行时间如下:

[x for x in a if x[0] in b]

# Exec time: 55.1 s ± 5.47 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

如您所见,numpy 运行得更快。您还可以将 python 列表转换为 numpy,反之亦然 simply.

a = [[1,0],[2,0],[3,0],[4,0]]
b = [2,4,7,8]
def return_common_elemens(a,b):
        for subval in a:
            if subval[0] in b:
                yield subval

print(list(return_common_elemens(a,b)))
>>>[[2, 0], [4, 0]]

最佳解决方案(至少我的具体情况)是由 schwobasegglNovin Shahroudi

提供的

我目前正在使用 schwobaseggl 的建议,因为我正在从 SQL 查询中读取数据,而 Novin Shahroudi 解决方案要求我进行更多数据类型转换。