Python 旋转子数组内的元素



我正在尝试按给定顺序创建两个子数组,在这种情况下,我有两个整数 a 和 ba表示子数组范围的值,b表示需要旋转多少次。

我像这样创建了子数组;

def reorder(a,b):
return [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]

假设a10,b1,输出是:

[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]

但是,如何将每个子阵列反转b次呢?

我想要的输出;

[[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]

您可以通过切片来旋转内部列表:

def reorder(a,b):
slicingPosition = a/2 % b
return [y[-slicingPosition:] + y[:-slicingPosition] for y in [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]]

for x in range(1, 6):
print(x, '>>', reorder(10, x))

输出:

(1, '>>', [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
(2, '>>', [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])
(3, '>>', [[3, 4, 0, 1, 2], [8, 9, 5, 6, 7]])
(4, '>>', [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])
(5, '>>', [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])

你可以弹出每个子数组的最后一个元素 b 次并将其插入开头:

def reorder(a,b):
suba = [i for i in range(0, a//2)] 
subb = [f for f in range(a//2, a)]
for i in range(b):
suba = [suba.pop(-1)]+suba
subb = [subb.pop(-1)]+subb
return [suba,subb]

In[1]:  reorder(10,1)
Out[1]: [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]

您可以使用具有内置rotate()函数的双端 que,

from collections import deque
def reorder(a,b):
my_arr   = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
first_q  = deque(my_arr[0])
second_q = deque(my_arr[1])
first_q.rotate(b)
second_q.rotate(b)
return [list(first_q), list(second_q)]

print(reorder(10, 1))

您也可以使用索引。这样:

def reorder(a, b):
tmp = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
tmp[0] = tmp[0][-b:] + tmp[0][:-b]
tmp[1] = tmp[1][-b:] + tmp[1][:-b]
return tmp
reorder(10, 1)

输出:

[[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]
<小时 />

编辑

对于b大于a/2的边缘情况。这样使用模数:

def reorder(a, b):
sz = a//2
r = b%sz
tmp = [[i for i in range(0, sz)]] + [[f for f in range(sz, a)]]
tmp[0] = tmp[0][-r:] + tmp[0][:-r]
tmp[1] = tmp[1][-r:] + tmp[1][:-r]
return tmp
reorder(10, 7)
[[3, 4, 0, 1, 2], [8, 9, 5, 6, 7]]

这也可以在莫里斯·迈耶的答案中完成(迄今为止最好的(。

我也想出了这些解决方案。

具有 numpy 的滚动功能;

import numpy as np
def reorder(a, b):
return [list(np.roll(v,b)) for v in [list(range(a//2)),list(range(a-a//2,a))]]  
In:  reorder(10,9)  
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]  

具有numpy滚动功能的解决方案也简单得多;

import numpy as np
def reorder(a, b):
return np.roll(np.arange(a).reshape(2, -1), b, 1).tolist()
In:  reorder(10,9)  
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]] 

如果您不想使用包装并且您可以接受一点眼睛出血;

def reorder(a, b):
return [list(range(a//2))[-b%(a//2):] + list(range(a//2))[:-b%(a//2)], list(range(a//2, a))[-b%(a//2):] + list(range(a//2, a))[:-b%(a//2)]]
In: reorder(10,9)  
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]] 

如果适用,我建议使用 deque。 我希望它能更快

import collections
def reorder(a,b):
tmp = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
for i in range(len(tmp)):
tmp[i] = collections.deque(tmp[i])
# rotates to right for positive numbers
tmp[i].rotate(b)
print d
>>> deque([3, 4, 5, 1, 2])

最新更新