我有一个相对较大的数组,称为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