将数字从一个列表移动到另一个列表的最快方法

时间:2012-11-27 20:06:23

标签: python list optimization iteration

我有一个清单:

list1=[1,8,2,9,3,8,7,10]

我想知道将所有值拉到“7”以上并将它们放入新列表的绝对最快方法。我不想使用for循环,当列表中有数亿个项目时,这需要太长时间。

理想情况是这样的:

list1=[1,8,2,9,3,8,7,10]
list2=AboveNumber(7,list1)
print list2
>>>[8,9,8,10]

感谢您的任何建议! 处理时间受到赞赏!

3 个答案:

答案 0 :(得分:2)

我不会过于担心维护已排序的订单并使用numpy

import numpy as np
a = np.arange(50)
print a[a >= 7]

#[ 7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49]

如果您有已经排序的项目,您可以使用bisect模块(或numpy有自己的方法来处理排序数据):

import bisect

items = range(50)
index = bisect.bisect_left(items, 7)
print items[index:]
# [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]

并按排序顺序添加项目:

bisect.insort_left(items, 3)
print items
#[0, 1, 2, 3, 3, 4, 5, .. snip ...]

答案 1 :(得分:2)

如上所述,第一个解决方案是将列表排序并仅保留有趣值之后的部分。使用ipython cell timeit

data = randint(10,size=2000)

天真的方法

%%timeit
[ i for i in data if i>7 ]
# 1.8 ms per loop

排序方法

data2 = sorted(data)
import bisect

%%timeit
data2[bisect.bisect(data2,7):]
# 13.6 us per loop

但总的来说,如果你必须处理数值数据,我强烈建议使用 numpy 库。使用朴素方法已经几乎与排序方法一样快

import numpy as np
adata = np.array(data)

%%timeit
adata[adata>7]
# 28.5 us per loop

但即使使用numpy数组也可以使用排序方法:

adata.sort()

%%timeit
adata[adata.searchsorted(7):]
# 2.1 us per loop

数组越大,numpy数组的性能越大,接近优化的C例程(实际上,它们是一堆优化的C代码,你只需支付调用python包装器的重载)

编辑:

请注意,速度之间的关系因数组大小而异。对于大约5 * 10 ^ 5个元素,naive numpy方法和列表的排序方法速度相同,而在相同大小的情况下,使用排序数组的numpy方法或多或少快3000倍。

答案 2 :(得分:1)

AboveNumber不会有任何魔力。如果列表无序,则必须遍历列表中的所有项目。

您可以通过按顺序维护列表来优化此操作,即确保在插入或删除后始终对列表进行排序。

如果订购了这个列表,你可以通过二进制搜索找到你的“mean”,这比运行所有列表要快得多,然后在那个位置剪切列表。