[英]Range with repeated consecutive numbers
我想创建一个范围(例如 (1, 5))的数字,并带有一些重复(例如 4):
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
一种方法是写:
list(itertools.chain(*([x] * 4 for x in range(1, 5))))
或者类似的:
list(itertools.chain(*(itertools.repeat(x, 4) for x in range(1, 5))))
然而,有一个平坦化的步骤,这是可以避免的。
是否有更pythonic或更紧凑的版本来生成这样的序列?
您可以改为使用列表理解。
l = [i for i in range(1, 5) for _ in range(4)]
输出
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
您的解决方案没有任何问题。 但是您可以使用chain.from_iterable
来避免解包步骤。
否则,我唯一的其他推荐是 NumPy,如果您愿意使用 3rd 方库。
from itertools import chain, repeat
import numpy as np
# list solution
res = list(chain.from_iterable(repeat(i, 4) for i in range(1, 5)))
# NumPy solution
arr = np.repeat(np.arange(1, 5), 4)
尝试这个,
range(1,5)*4 # if you don't consider order
sorted(range(1,5)*4) # for ordered seq
随着性能更新。
Mihai Alexandru-Ionut 答案:
%timeit [i for i in range(1, 5) for _ in range(4)]
1000000 loops, best of 3: 1.91 µs per loop
jpp 回复:
%timeit list(chain.from_iterable(repeat(i, 4) for i in range(1, 5)))
100000 loops, best of 3: 2.12 µs per loop
%timeit np.repeat(np.arange(1, 5), 4)
1000000 loops, best of 3: 1.68 µs per loop
罗里·道尔顿回答:
%timeit [n for n in range(1,5) for repeat in range(4)]
1000000 loops, best of 3: 1.9 µs per loop
杰沃德回答:
%timeit list(i//4 for i in range(1*4, 5*4))
100000 loops, best of 3: 2.47 µs per loop
RoadRunner 评论区推荐:
%timeit for i in range(1, 5): lst.extend([i] * 4)
1000000 loops, best of 3: 1.46 µs per loop
我的答案:
%timeit sorted(range(1,5)*4)
1000000 loops, best of 3: 1.3 µs per loop
我认为chain
+ repeat
可能是你最好的选择。 话虽如此,
start = 1
stop = 5
repeat = 4
x = list(i//repeat for i in range(start*repeat, stop*repeat))
print(x)
应该有效(至少对于正参数)。
我非常喜欢简单易懂的代码。 有了这种哲学,我会用
[n for n in range(1,5) for repeat in range(4)]
我只想提一下, extend
也可能是一种选择。 也许不如单行列表理解那么漂亮,但是当buckets
的大小增加时它会表现得更好
def listExtend():
a = []
for i in range(1,5):
a.extend([i]*4)
return a
def listComprehension():
return [[i,x] for i in range(1, 5) for x in range(4)]
import timeit
print(timeit.timeit(stmt="listComprehension()", setup="from __main__ import listComprehension", number=10**7))
print(timeit.timeit(stmt="listExtend()", setup="from __main__ import listExtend", number=10**7))
14.2532608
8.78004566
一种选择,虽然它需要安装一个包,但它是itertation_utilities.replicate
:
>>> from iteration_utilities import replicate
>>> list(replicate(range(1, 5), 4))
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
如果你不想安装那个包, replicate
函数本质上等同于这个函数:
from itertools import repeat
def replicate(items, repeats):
for item in items:
for _ in repeat(None, repeats):
yield item
以防万一您对性能感兴趣,我为几个(不是全部)提议的替代方案做了一些微基准测试:
如您所见,NumPy 和iteration_utilities
方法最快,而所有其他方法的速度大致相同。
有趣的是,在这些其他方法中, list.extend
方法最快,(我的)自定义生成器最慢。 我没想到。
这是复制基准的代码:
from iteration_utilities import replicate
from itertools import chain, repeat
import numpy as np
def replicate_generator_impl(upper):
for item in range(1, upper):
for _ in repeat(None, 4):
yield item
def replicate_generator(upper):
return list(replicate_generator_impl(upper))
def iteration_utilities_replicate(upper):
return list(replicate(range(1, upper), 4))
def double_comprehension(upper):
return [i for i in range(1, upper) for _ in range(4)]
def itertools_chain(upper):
return list(chain(*([x] * 4 for x in range(1, upper))))
def itertools_chain_from_iterable(upper):
return list(chain.from_iterable(repeat(i, 4) for i in range(1, upper)))
def extend(upper):
a = []
for i in range(1, upper):
a.extend([i] * 4)
return a
def numpy_repeat(upper):
return np.repeat(np.arange(1, upper), 4)
from simple_benchmark import benchmark
funcs = [replicate_generator, iteration_utilities_replicate, double_comprehension, itertools_chain, itertools_chain_from_iterable, extend, numpy_repeat]
arguments = {2**i: 2**i for i in range(1, 15)}
b = benchmark(funcs, arguments, argument_name='size')
b.plot()
如果您想知道没有 NumPy 方法会是什么样子:
免责声明:我是iteration_utilities
和simple_benchmark
的作者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.