【问题标题】:Faster way of getting elements in list by index [duplicate]按索引获取列表中元素的更快方法[重复]
【发布时间】:2018-07-01 08:22:45
【问题描述】:

我有一个包含约 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 成为set。如果是列表,难怪它为什么慢。

标签: python algorithm


【解决方案1】:

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 步,所以不值得你花时间在第一种方法上,因为这里的效率是第一种方法的两倍多。

【讨论】:

  • 我理解你回答的第一部分。在第二部分中,我能否澄清一下为什么索引必须按照正确的顺序才能让您以这种方式循环它们?
  • @Tim 取决于:如果p 未排序,则第二部分会产生不同的输出,因为您会按照p 列出它们的顺序生成值。如果没问题,那就坚持第二个版本不管p是否被排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 2022-08-17
  • 2020-12-27
  • 2013-12-03
  • 2013-08-29
相关资源
最近更新 更多