我有一个包含~11,000个元素的python列表 e 。然后我有一个<3,000>元素的索引列表 p 。
我想过滤 e ,只保留 p 中指定的索引处的元素。
到目前为止,我使用简单的列表理解:
f = [x for i,x in enumerate(e) if i in p]
但是,这个实现需要大约1秒。
这可能不会太多,但由于我必须为10,000个列表执行此操作,因此它会超过2个小时。然后,我必须再次重复这200个批次的10,000个列表,所以它真的太慢了。
我知道如何以更快的方式达到相同的结果吗?
答案 0 :(得分:5)
将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
以选择元素:< / p>
f = [e[i] for i in p]
现在你只需要3k步。
如果未对p
进行排序,则第二个版本将按照与e
中列出的顺序不同的顺序生成项目。这可能没问题,或者您可以先排序p
。但是,排序需要O(N log N)个步骤; p
中的3k项目需要3k次log(3k)== 3k次8 = 24k步骤,所以不值得你在这里第一种方法的时间,这是效率的两倍以上。