我有一个包含 ~11,000 个元素的 python 列表 e。然后我有一个索引列表 p ~3,000 个元素。
我想过滤 e 以仅保留 p 中指定索引处的元素。
到目前为止,我使用的是简单的列表推导式:
f = [x for i,x in enumerate(e) if i in p]
但是,此实现需要大约 1 秒。
这可能不会太多,但由于我必须为 10,000 个列表执行此操作,因此需要 2 个多小时。然后我必须对 200 个批处理的 10,000 个列表再次重复此操作,所以它真的太慢了。
关于如何以更快的方式实现相同结果的任何想法?
将 p
变成一个集合。 i in p
针对列表的包含测试需要 O(length_of_list) 线性时间,而针对集合的测试需要 O(1) 常数时间:
p_set = set(p)
f = [x for i, x in enumerate(e) if i in p_set]
这使得过滤成为 O(length_of_e) 操作,因此有 11k 步。使用 p
列表,您可以组成 O(length_of_e * length_of_p) 步,因此 33 百万。
但是,如果 p
是一个已排序列表,您的索引已经按照正确的顺序排列,您可以循环遍历 p
选择元素:
f = [e[i] for i in p]
现在您只走了 3k 步。
如果 p
未排序,则第二个版本将以与它们在 e
中列出的顺序不同的顺序生成项目。那可能没问题,或者您可以先对 p
进行排序。但是,排序需要 O(N log N) 个步骤; p
中有 3k 个项目需要 3k 次 log(3k) == 3k 次 8 == 24k 步,所以不值得你花时间在第一种方法上,这里的效率是这里的两倍多.