如何有效过滤大型python列表



我有一个相对较大的数组,称为allListings,并希望过滤掉allListings[:][14] == listingID所在的所有行。

这是我正在使用的代码:tempRows = list(filter(lambda x: x[14] == listingID, allListings))

对于所有不同的listingID,在for循环中重复过滤

评测显示,这一行占用了循环中95%的运行时间。有没有其他方法可以更有效地过滤大型阵列?

正如注释中所建议的,如果您根据该列的值对其执行多个操作,则可能需要按该列进行排序和分组。

>>> from itertools import groupby
>>> a = [[1, 2, 3, 5],
...      [4, 6, 2, 8],
...      [1, 5, 7, 9],
...      [3, 5, 8, 2]]
>>> b = sorted(a, key=lambda x: x[0])
>>> b
[[1, 2, 3, 5], [1, 5, 7, 9], [3, 5, 8, 2], [4, 6, 2, 8]]
>>> c = groupby(b, key=lambda x: x[0])
>>> c
<itertools.groupby object at 0x106b763e0>
>>> d = {k: list(v) for k, v in c}
>>> d
{1: [[1, 2, 3, 5], [1, 5, 7, 9]], 3: [[3, 5, 8, 2]], 4: [[4, 6, 2, 8]]}

现在,如果您需要第一个元素为1的所有列表,您只需要:

>>> d[1]
[[1, 2, 3, 5], [1, 5, 7, 9]]

或者,如果你想要1在第一个位置的所有东西。

>>> [x for k, v in d.items() 
...    if k != 1 
...    for x in v] 
[[3, 5, 8, 2], [4, 6, 2, 8]]

这显然是一个更简单的例子,但应该很容易适用于您的情况。

通过将过滤器移动到cython文件并进行编译,我获得了大约33%的改进。我认为主要的加速是消除每次比较的listingID的重新加载。只是猜测而已。

test.pyx

def all_listings_filter(list data, int listingID):
return [row for row in data if row[14] == listingID]

命令行

cython3 test.pyx
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python3.10 -o test.so test.c

最新更新