通过动态循环迭代(Python)
我正在使用python对一些数字进行排序。我想创建一个函数,它允许我输入一个值(4,8,16,32,64等),创建一个数组数组,并重新排列它们的序列。通过动态循环迭代(Python)
我已经添加数字如何确定值= 4的序列,其细节和8
对于值= 4阵列(X = [0,1,2,3])应当被拆分在两个([0,1]和[2,3])中,然后根据每个数组中的第一个数字([0,2,1,3])进行组合。
对于值= 8阵列(X = [0,1,2,3,4,5,6,7])应被分成两个([0,1,2,3 ]和[4,5,6,7])。两个数组应该再次分成两部分([0,1,2,3]分为[0,1]和[2,3]和[4,5,6,7]分为[4,5]和[6, 7])。然后根据每个数组中的第一个数字和第二组数组的顺序([0,4,2,6,1,5,3,7])组合数组。
我不知道如何处理递归(动态嵌套的循环)。我试图循环通过拆分数组创建的每个布尔。我研究过itertools和递归(Function with varying number of For Loops (python)),但我无法使它工作。下面,我添加了代码来说明迄今为止我的方法。
任何帮助,非常感谢。我也接受其他想法来确定序列。
我使用python 2.7.6和numpy。
代码:
import numpy
value = 4
a = []
x = numpy.arange(value)
y = numpy.array_split(x, 2)
for i in range(2):
for j in y:
a.append(j.tolist()[i])
print(a)
输出:
[0, 2, 1, 3]
代码:
import numpy
value = 8
a = []
x = numpy.arange(value)
y = numpy.array_split(x, 2)
for i in range(2):
for h in range(2):
for j in y:
z = numpy.array_split(j, 2)
a.append(z[h][i])
print(a)
输出:
[0, 4, 2, 6, 1, 5, 3, 7]
value = 16的输出应该是[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]。
下面是使用np.transpose
和reshaping
一个NumPythonic方式 -
def seq_pow2(N):
shp = 2*np.ones(np.log2(N),dtype=int)
return np.arange(N).reshape(shp).transpose(np.arange(len(shp))[::-1]).ravel()
请注意,.transpose(np.arange(len(shp))[::-1]
将简化为.T
,所以我们将有一个简化版本 -
def seq_pow2(N):
shp = 2*np.ones(np.log2(N),dtype=int)
return np.arange(N).reshape(shp).T.ravel()
可以进一步简化和替换转置一起做ravel
/flattening
在列主要排序像fortran
与.ravel('F')
最终导致我们 -
def seq_pow2(N):
shp = 2*np.ones(np.log2(N),dtype=int)
return np.arange(N).reshape(shp).ravel('F')
样品试验 -
In [43]: seq_pow2(4)
Out[43]: array([0, 2, 1, 3])
In [44]: seq_pow2(8)
Out[44]: array([0, 4, 2, 6, 1, 5, 3, 7])
In [45]: seq_pow2(16)
Out[45]: array([ 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15])
要做到这一点是不使用 for循环,但做一些数组操作与numpy的最简单的方法。
N = 8
pow2 = np.log2(N)
out = np.arange(N).reshape([2]*pow2).transpose(np.arange(pow2)[::-1]).flatten()
array([0, 4, 2, 6, 1, 5, 3, 7])
这样做是它重塑x
成n
维阵列,其中n
为2对应于的x
长度的功率。在这个整形之后,每个维度的长度都是2.然后我们扭转所有维度并将其平坦化以得到您想要的数组。
编辑
这是一个类似的方法来Divakar's Solution,和他结束了简明得多做这件事,但我就离开这个位置留给后人。
蟒蛇递归版本,为了清楚:
def rec(n):
if n==1 : return [0]
l=[0]*n
l[::2]=rec(n//2)
for i in range (0,n,2) : l[i+1]=l[i]+n//2
return l
为
In [6]: rec(16)
Out[6]: [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
或者,观测结果的二进制表示,一个numpy的解决方案:
def rearange(N):
u=2**arange(N.bit_length()-1)
v=arange(N)
bits= u[None,:] & v[:,None]
return sum(bits*u[::-1],1)
你需要numpy的解决方案?这可以用普通的python完成,我认为 –
我想说的是,你需要的是采取数字的二进制形式并对其进行antialphabetically排序 – Ilja