通过索引获取列表中元素的更快方法

MrD*_*MrD 0 python algorithm

我有一个包含~11,000个元素的python列表e.然后,我有索引列表p〜3000元的.

我想过滤e以仅保留p中指定的索引处的元素.

到目前为止,我正在使用简单的列表理解:

f = [x for i,x in enumerate(e) if i in p]
Run Code Online (Sandbox Code Playgroud)

但是,这种实现需要大约1秒.

这可能不会太多,但由于我必须为10,000个列表执行此操作,因此它将超过2个小时.然后,我必须再次重复这200个批次的10,000个列表,所以它真的太慢了​​.

知道如何以更快的方式达到相同的结果吗?

Mar*_*ers 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]
Run Code Online (Sandbox Code Playgroud)

这使得过滤O(length_of_e)操作,因此11k步.使用p列表,您可以达到O(length_of_e*length_of_p)步骤,因此达到3300 .

但是,如果p排序列表,您已经按正确的顺序排列了索引,并且可以循环p选择元素:

f = [e[i] for i in p]
Run Code Online (Sandbox Code Playgroud)

现在你只需要3k步.

如果p未排序,则第二个版本将按照与其列出的顺序不同的顺序生成项目e.那可能没问题,或者你可以p先排序.但是,排序需要O(N log N)个步骤; 有3k项目p,需要3k次日志(3k)== 3k次8 == 24k步骤,所以不值得你在这里超过第一种方法的时间,这是效率的两倍以上.

  • @Tim取决于:如果`p`没有排序,第二部分产生不同的输出,然后你按顺序生成值'p`列出它们.如果没关系,那么只要坚持使用第二个版本而不管`p`被分类. (2认同)