Understanding Any Number of Nests Loop Processing in Python

Asked 2 years ago, Updated 2 years ago, 51 views

I would like to create the following functions, but I would like to know how to loop any number of times.

1. As an argument, take two functions: (1) an arbitrary number of dimensions of numpy array, and (2) a processing corresponding to each dimension.
②All array elements are processed.However, the action is based on the function specified as the argument.

At this time, you do not know how to create any number of nested operations.
For example, if it's a 4D array, it's dirty, but

 x = NDARRAY.shape
for i in range (x[0]):
    for jin range (x[1]):
        fork in range (x[2]):
            for line range (x[3]):

You can do this, but what do you usually do when you're in n-dimensional?
Do I need knowledge of meta-programming?

python numpy

2022-09-30 14:35

3 Answers

This is an example implementation that recursively represents a nest of any depth.
実装Implementation Example <

import numpy as np
def loopoop(func, na, dims=None, indexes=[], level=0, no=0, first=True):
    if dims is None:
        dims = na.shape
    if first:
        indexes=[0]*len(dims)
    iflen(dims)<=0:
        func(na,indexes)
        return
    for i in range (dims[0]):
        indexes [level] = i
        loopoop(func, na, dims[1:], indexes=indexes, level=level+1, no=i, first=False)

def func1(na,indexes):
    print("Hello:indexes="+str(indexes))

na = np.ndarray ((2,3,4,5))

loopoop(func1,na)
  • Processing name
    loopoop

  • (1) Any number of dimensions of numpy array
    na

  • 各Function that performs processing corresponding to each dimension
    func
  • func first argument (number array)
    na
  • func second argument (index)
    indexes

Processing Name
loopoop

任意 Any number of numpy arrays
na

Caution
In KLC's answer, I think it would be advantageous in terms of speed to manage the multi-dimensional array data in one-dimensional array.

[Multidimensional]

Sizett[SIZE_1][SIZE_2][SIZE_3][SIZE_4]
Index tttt[i1][i2][i3][i4]

[1D]

Size t[SIZE_1*SIZE_2*SIZE_3*SIZE_4]
index t[i]
i=i1*SIZE_2*SIZE_3*SIZE_4
  + i2*SIZE_3*SIZE_4
  + i3*SIZE_4
  + i4

Calculate each index from i using the following formula:

i1=(i%(SIZE_1*SIZE_2*SIZE_3*SIZE_4)//(SIZE_2*SIZE_3*SIZE_4)
    i2=(i%(SIZE_2*SIZE_3*SIZE_4)//(SIZE_3*SIZE_4)
    i3=(i%(SIZE_3*SIZE_4))//(SIZE_4)
    i4=(i%SIZE_4)


2022-09-30 14:35

It would be good to use nditer with multi_index flag.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.nditer.html

import numpy as np

x = np.random.randn(2,3)

it=np.nditer(x,flags=['multi_index'])

while not.finished:
    # do something with x and it.multi_index
    print(it.multi_index)
    print(x[it.multi_index])

    # move on
    it.iternext()
(0,0)
0.23465161779473015
(0, 1)
0.22383801010291296
(0, 2)
-0.8051323435933129
(1, 0)
0.8931324229893808
(1, 1)
-0.4271553422304515
(1, 2)
-2.146703943718106
#Different dimensions of data
x = np.random.randn(2,3,2)

# The code below is exactly the same.
it=np.nditer(x,flags=['multi_index'])

while not.finished:
    print(it.multi_index)
    print(x[it.multi_index])
    it.iternext()
 (0,0,0)
0.30500812464361104
(0, 0, 1)
0.7671660280535492
(0, 1, 0)
-0.87198212525212
(0, 1, 1)
-0.6311542834847657
(0, 2, 0)
0.5198028854150701
(0, 2, 1)
0.8153458301759646
(1, 0, 0)
-0.7942063485178719
(1, 0, 1)
-1.568633897435036
(1, 1, 0)
-1.3299054158710617
(1, 1, 1)
-0.4096393538574391
(1, 2, 0)
-0.03538806394741229
(1, 2, 1)
0.5462354038739015


2022-09-30 14:35

How about this?The idea is to generate subscripts and then scan all the elements in a single loop:

import it tools
import numpy as np


# main
def(A,g):
  for idx in intertools.product (*[range(n) for n in A.shape]):
    g(A,A[idx],*idx)


# callback
defh(Arr, Elm, *idx):
  assert Arr [idx] == Elm
  print('Arr[%s]=%f'%(str(idx), Elm))


# For example...
shape=(2,3,4,5)
X=np.range(np.product(shape)) .reshape(shape)
f(X,h)

Sample Output:

Arr[(0,0,0,0)] = 0.000000
Arr [(0,0,0,1)] = 1.000000
Arr [(0,0,0,2)] = 2.000000
Arr [(0,0,0,3)] = 3.000000
Arr [(0,0,0,4)] = 4.000000
...


2022-09-30 14:35

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.