构建Python列表的最有计算效率的方法,重复和迭代数字,如[0,0,0,1,1,1,2,2,2。 。 。 ,等等]

时间:2018-05-31 20:21:19

标签: python

我想创建一个类似于

的数组
[0, 0, 0, 1, 1 , 1, 2, 2, 2,  . . .etc]

[4,4,4,4,5,5,5,5,6,6,6,6,... 。 。等]

有类似

的内容
segments = [i for i in range(32)]  

将使

 [ 1, 2, 3, 4, 5, . . . etc]

有些方法我可以调用3个独立的i in range(32)集,但我希望通过只调用一次来节省计算。

制作像

这样的数组的计算效率最高,编程最优雅的方法是什么
[0, 0, 0, 1, 1 , 1, 2, 2, 2,  . . .etc]

5 个答案:

答案 0 :(得分:7)

itertools.chain iterables上使用itertools.repeat

import itertools

result = list(itertools.chain.from_iterable(itertools.repeat(i,3) for i in range(32)))

print(result)

结果:

  

[0,0,0,1,1,1,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7, 7,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,13,14,14,14,15,15,15, 16,16,16,17,17,17,18,18,18,19,19,19,20,20,20,21,21,21,22,22,22,23,23,23,24, 24,24,25,25,25,26,26,26,27,27,27,28,28,28,29,29,29,30,30,30,31,31,31]

这种技术避免了创建中间列表并最小化纯python循环(一个python循环总计,使用map可以删除最后一个,但这需要lambda case,增加了一个函数调用。)

编辑:让我们回答这个问题并Ted's answer

import itertools,time

n=1000000

start_time = time.time()
for _ in range(n):
    list(itertools.chain.from_iterable(itertools.repeat(i,3) for i in range(32)))

print("itertools",time.time() - start_time)

start_time = time.time()
for _ in range(n):
    [i for i in range(32) for _ in range(3)]
print("flat listcomp",time.time() - start_time)

结果:

itertools 10.719785928726196
flat listcomp 13.869723081588745

因此使用itertools而不是list comprension的速度提高约30%(python 3.4,windows)

注意:

少量重复会在内循环中产生大量itertools.repeat次调用,因此在3次重复的情况下,执行NickA suggests的速度会更快:

list(itertools.chain.from_iterable((i,)*3 for i in range(32)))

(上述替补席上7秒对10分)

numpy解决方案更快(约1.5秒),如果您可以使用numpy

import numpy as np
np.arange(32).repeat(3)  # credits: liliscent 

答案 1 :(得分:4)

只需在列表推导中使用嵌套循环。

segments = [i for i in range(32) for _ in range(3)]

输出:

[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31]

答案 2 :(得分:2)

使用场地划分:

userid

示例输出:

then

如果你真的想要一个def repeated_value_list(repeats, start, stop=None): if stop is None: start, stop = 0, start return [x//repeats for x in range(start*repeats, stop*repeats)] 数组,那就更有效了,因为广播可以在不理解的情况下进行分配:

>>> repeated_value_list(3, 5)
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]

>>> repeated_value_list(3, 4, 10)
[4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9]

输出:

numpy

答案 3 :(得分:1)

如果我们有[(0, 0, 0), (1, 1, 1), …],我们只需要压扁它:

[elem for sublst in lst for elem in sublst]

我们如何做到这一点?好吧,如果我们有三个单独的序列[0, 1, 2, …],我们可以zip将它们放在一起:

lst = zip(r1, r2, r3)

这三个序列只是range(32)

lst = zip(range(32), range(32), range(32))

...或者,如果你想要它是动态的而不是完全是32和3:

lst = zip(*(range(count) for _ in range(reps)))

无论哪种方式,你都可以把它组合成一个单行:

[elem for sublst in zip(*(range(count) for _ in range(reps))) for elem in sublst]

然后你可以简化:

[elem for elem in range(count) for _ in range(reps)]

答案 4 :(得分:0)

您可以使用itertools.chain.from_iterable

执行此操作
>>> list(itertools.chain.from_iterable([[i]*3 for i in range(32)]))
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31]