Python 按索引获取列表中元素的更快方法
我有一个python列表e,包含约11000个元素。然后我有一个包含3000个元素的索引列表 我想筛选e以仅保留p中指定索引处的元素 到目前为止,我使用的是简单的列表理解:Python 按索引获取列表中元素的更快方法,python,algorithm,Python,Algorithm,我有一个python列表e,包含约11000个元素。然后我有一个包含3000个元素的索引列表 我想筛选e以仅保留p中指定索引处的元素 到目前为止,我使用的是简单的列表理解: f = [x for i,x in enumerate(e) if i in p] 但是,此实现需要~1秒 这可能不多,但由于我必须为10000个列表执行此操作,因此它将超过2个小时。然后我不得不对200批10000个列表重复这一过程,所以速度实在太慢了 你知道我怎样才能更快地达到同样的效果吗?把p变成一个集合。p中的i针
f = [x for i,x in enumerate(e) if i in p]
但是,此实现需要~1秒
这可能不多,但由于我必须为10000个列表执行此操作,因此它将超过2个小时。然后我不得不对200批10000个列表重复这一过程,所以速度实在太慢了
你知道我怎样才能更快地达到同样的效果吗?把
p
变成一个集合。p中的i
针对列表的包容测试需要O(列表的长度)线性时间,而针对集合的测试需要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
a列表,您可以完成O(length_of_e*length_of_p)步数,因此达到3300万步
但是,如果p
是一个已排序的列表,则索引的顺序已经正确,您只需循环p
即可选择元素:
f = [e[i] for i in p]
现在你只走了3公里
如果未对
p
进行排序,则第二个版本将按照与e
中所列项目不同的顺序生成项目。这可能很好,或者您可以先排序p
。然而,排序需要O(N logn)个步骤;由于p
中的3k项需要3k次log(3k)==3k次8==24k步数,因此与第一种方法相比,在这里花费的时间不值得,因为第一种方法的效率是第一种方法的两倍多 将p
组合成一组。p中的i
针对列表的包容测试需要O(列表的长度)线性时间,而针对集合的测试需要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
a列表,您可以完成O(length_of_e*length_of_p)步数,因此达到3300万步
但是,如果p
是一个已排序的列表,则索引的顺序已经正确,您只需循环p
即可选择元素:
f = [e[i] for i in p]
现在你只走了3公里
如果未对
p
进行排序,则第二个版本将按照与e
中所列项目不同的顺序生成项目。这可能很好,或者您可以先排序p
。然而,排序需要O(N logn)个步骤;由于p
中的3k项需要3k次log(3k)==3k次8==24k步数,因此与第一种方法相比,在这里花费的时间不值得,因为第一种方法的效率是第一种方法的两倍多 使p
aset
。如果它是一个列表,难怪它速度慢。makep
aset
。如果是一张单子,难怪它慢。我理解你答案的第一部分。在第二部分中,我可以要求澄清为什么标记必须以正确的顺序排列,以便您以这种方式循环它们吗?@Tim这取决于:如果p
未排序,则第二部分会产生不同的输出,因为您随后会按p
列出的顺序生成值。如果可以的话,那么不管排序的是p
,只要坚持第二个版本就行了。我理解你答案的第一部分。在第二部分中,我可以要求澄清为什么标记必须以正确的顺序排列,以便您以这种方式循环它们吗?@Tim这取决于:如果p
未排序,则第二部分会产生不同的输出,因为您随后会按p
列出的顺序生成值。如果可以的话,那么不管排序的是p
,都要坚持第二个版本。