检查值或值列表是否是python中列表的子集的最快方法

时间:2019-07-08 08:17:33

标签: python list numpy cython

我有一个名为main_list的列表,它包含大约1300万个列表,每个列表都包含6个数字。我正在寻找一种过滤掉不包含某些值的列表的方法。例如,要创建一个仅包含值4和5的列表的新列表列表,我的代码将按以下方式工作:

and_include = []
temp_list=[4,5]
for sett in main_list:
    if set(temp_list).issubset(sett):
        and_include.append(sett)

这大约需要5秒钟才能运行,对于频繁使用而言可能会很烦人,所以我想知道使用numpy或cython是否有更快的方法?

我对cython不太熟悉,但是我尝试用这种方式实现,对其进行了编译,但都出现了错误。

def andinclude(list main_list,list temp_list):
    and_include=[]
    for sett in main_list:
        if set(temp_list).issubset(sett):
            and_include.append(sett)
    return and_include

希望有更快的方法吗?

2 个答案:

答案 0 :(得分:2)

这是一个numpy解决方案:

import numpy as np

# Randomly generate 2d array of integers
np.random.seed(1)
a = np.random.randint(low=0, high=9, size=(13000000, 6))

# Use numpy indexing to filter rows
results = a[(a == 4).any(axis=1) & (a == 5).any(axis=1)]

结果:

In [35]: print(results.shape)
(3053198, 6)

In [36]: print(results[:5])
[[5 5 4 5 5 1]
 [5 5 4 3 8 6]
 [2 5 8 1 1 4]
 [0 5 4 1 1 5]
 [3 2 5 2 4 6]]

时间:

In [37]: %timeit results = a[(a == 4).any(axis=1) & (a == 5).any(axis=1)]
923 ms ± 38.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

如果您需要将结果转换回列表列表,而不是二维numpy数组,则可以使用:

l = results.tolist()

这使我的机器上运行的时间增加了大约50%,但仍比任何涉及循环遍历Python列表的解决方案都要快。

答案 1 :(得分:0)

您可以使用列表理解而不是在循环中附加。另外,您可能希望将set(temp_list)的结果存储在本地变量中,这样就不会为相同的结果调用set 1300万次。