我想要生成一个循环的数字序列,例如[A B C A B C]
,其中任意长度N
我试过了:
import numpy as np
def cyclic(N):
x = np.array([1.0,2.0,3.0]) # The main sequence
y = np.tile(x,N//3) # Repeats the sequence N//3 times
return y
但是我的代码的问题是如果我输入任何不能被三个整数划分的整数,那么结果的长度(N
)将比我想象的要小。我知道这是一个非常新的问题,但我真的卡住了
答案 0 :(得分:5)
您可以使用numpy.resize
x = np.array([1.0, 2.0, 3.0])
y = np.resize(x, 13)
y
Out[332]: array([ 1., 2., 3., 1., 2., 3., 1., 2., 3., 1., 2., 3., 1.])
警告:这个答案没有扩展到2D,因为resize
会在重复之前展平数组。
答案 1 :(得分:2)
方法#1:这是一种使用modulus
处理通用序列以生成这些循环索引的方法 -
def cyclic_seq(x, N):
return np.take(x, np.mod(np.arange(N),len(x)))
方法#2:为了提高性能,这是另一种方法,它会将最大间隔数的多个切片,然后使用slicing
来选择第一个{ {1}}元素 -
N
样品运行 -
def cyclic_seq_v2(x, N):
return np.tile(x,(N+N-1)//len(x))[:N]
运行时测试
In [81]: cyclic_seq([6,9,2,1,7],14)
Out[81]: array([6, 9, 2, 1, 7, 6, 9, 2, 1, 7, 6, 9, 2, 1])
In [82]: cyclic_seq_v2([6,9,2,1,7],14)
Out[82]: array([6, 9, 2, 1, 7, 6, 9, 2, 1, 7, 6, 9, 2, 1])
在表现方面,In [327]: x = np.random.randint(0,9,(3))
In [328]: %timeit np.resize(x, 10000) # @Daniel Forsman's solution
...: %timeit list(itertools.islice(itertools.cycle(x),10000)) # @Chris soln
...: %timeit cyclic_seq(x,10000) # Approach #1 from this post
...: %timeit cyclic_seq_v2(x,10000) # Approach #2 from this post
...:
1000 loops, best of 3: 296 µs per loop
10000 loops, best of 3: 185 µs per loop
10000 loops, best of 3: 120 µs per loop
10000 loops, best of 3: 28.7 µs per loop
In [329]: x = np.random.randint(0,9,(30))
In [330]: %timeit np.resize(x, 10000) # @Daniel Forsman's solution
...: %timeit list(itertools.islice(itertools.cycle(x),10000)) # @Chris soln
...: %timeit cyclic_seq(x,10000) # Approach #1 from this post
...: %timeit cyclic_seq_v2(x,10000) # Approach #2 from this post
...:
10000 loops, best of 3: 38.8 µs per loop
10000 loops, best of 3: 101 µs per loop
10000 loops, best of 3: 115 µs per loop
100000 loops, best of 3: 13.2 µs per loop
In [331]: %timeit np.resize(x, 100000) # @Daniel Forsman's solution
...: %timeit list(itertools.islice(itertools.cycle(x),100000)) # @Chris soln
...: %timeit cyclic_seq(x,100000) # Approach #1 from this post
...: %timeit cyclic_seq_v2(x,100000) # Approach #2 from this post
...:
1000 loops, best of 3: 297 µs per loop
1000 loops, best of 3: 942 µs per loop
1000 loops, best of 3: 1.13 ms per loop
10000 loops, best of 3: 88.3 µs per loop
似乎运作良好。
答案 2 :(得分:1)
你可以使用itertools.cycle
这个无限迭代器:
>>> import itertools
>>> it = itertools.cycle([1,2,3])
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
1
您获得特定长度的序列(N
),并将其与itertools.islice
结合使用:
>>> list(itertools.islice(itertools.cycle([1,2,3]),11))
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2]
编辑:正如您在Divakar's benchmark中所看到的,与其他答案相比,这种方法在速度方面通常是中间的。当您需要迭代器return
而不是list
或numpy
数组时,我建议何时使用此解决方案。
答案 3 :(得分:1)
首先超长它(使用math.ceil
)然后resize
tile
import numpy as np
import math
def cyclic(N):
x = np.array([1.0,2.0,3.0]) # The main sequence
y = np.tile(x, math.ceil(N / 3.0))
y = np.resize(y, N)
return y
在考虑Daniel Forsman的建议后,可将其简化为
import numpy as np
def cyclic(N):
x = np.array([1.0,2.0,3.0]) # The main sequence
y = np.resize(x, N)
return y
因为np.resize
会自动在1D
答案 4 :(得分:0)
你可以使用itertools循环。
In [3]: from itertools import cycle
In [4]: for x in cycle(['A','B','C']):
...: print(x)
...:
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
修改强> 如果要使用out循环实现它,则需要递归函数。基于itertools循环等的解决方案只是隐藏导入函数后面的循环。
In [5]: def repeater(arr, n):
...: yield arr[0]
...: yield arr[1]
...: yield arr[2]
...: if n == 0:
...: yield StopIteration
...: else:
...: yield from repeater(arr, n-1)
...: