''' Two Python3 implementations of dynamic loops, indefinite layers of loops (recursive, pure loops) # Note: Python only has list type by default, just understand it as an array of C. # To take 3 elements from the following 3 arrays to form one, and print out the possible combinations data = [ [1, 2], [3, 4, 5], [6, 7, 8, 9] ] # Means that there will be 2 * 3 * 4 = 24 possibilities, that is, the Deca product of all lists, the solution can be implemented with a triple loop for example: for i in data[0]: for j in data[1]: for k in data[2]: print([i, j, k]) But if the number of arrays in data is uncertain, how to implement a dynamic indefinite layer loop? I think of data as a two-dimensional array: The first dimension is the number of data containing the array, that is, the Y axis, starting from 0 and increasing from line to line; The second dimension is the number of elements contained in each array, that is, the X axis, starting from 0 and increasing column by column from left to right; Then use recursive and pure loop to process the X and Y axes respectively. ''' ''' Recursive method From the first layer of the Y axis, index = 0, recursively from top to bottom, and when the bottom layer is reached, a loop is used to add one element of the bottom layer to the list to be returned. Note: Python has a limit on the number of recursive layers, and different operating systems have different limits. It is necessary to consider another algorithm when it is above 100 layers. ''' # data data source, cur_y_idx current Y-axis value, lst_rst return result list, lst_tmp is used to temporarily assemble elements of lst_rst def dynloop_rcsn(data, cur_y_idx = 0, lst_rst = [], lst_tmp = []): max_y_idx = len (data)-1 # Get the maximum index value of Y axis for x_idx in range (len (data [cur_y_idx])): # traverse the X axis of the current layer lst_tmp.append (data [cur_y_idx] [x_idx]) # Append the elements of the X axis of the current layer to lst_tmp if cur_y_idx == max_y_idx: # If the current layer is the bottom layer, append lst_tmp as an element to lst_rst lst_rst.append([*lst_tmp]) else: # If the current is not the bottom layer, the Y axis +1 continues to recursively, so the maximum number of recursive layers is the maximum value of the Y axis # The addresses of lst_rst and lst_tmp are also passed to the next recursion, so that the same list object is modified no matter which layer is modified dynloop_rcsn(data, cur_y_idx+1, lst_rst, lst_tmp) lst_tmp.pop () # At the end of this loop, whether it is recursively returned or the bottom loop, the last element of lst_tmp must be removed return lst_rst ''' Round robin The multilevel loop is 'flattened' into a one-level loop, that is, the Y axis has only 0, and only the X axis is traversed, and the 2-dimensional array becomes a 1-dimensional array. The difficulty is that each loop must calculate the index of each extracted element to extract the elements in the original 2D array. ''' def dynloop_loop(data): # Variable initialization max_y_idx = len (data) # Get the maximum value of the Y axis of the original 2D array row_max_idx = 1 # Record the maximum value of the X axis, the initial value is 1, the following calculation arr_len, lst_row, lst_rst = [], [], [] arr_idx = [0] * max_y_idx # Save the set of index values of max_y_idx elements extracted each time, the initial value is [0, 0, 0, 0] # Convert 2-dimensional array data to 1-dimensional array lst_row for item in data: _n = len (item) # Find the length of each layer in the original 2-dimensional array arr_len.append (_n) # Save the set of the length of each layer in the original 2D array lst_row + = item # accumulate each element of the original 2-dimensional array into the 1-dimensional array lst_row row_max_idx * = _n # record the total number of loops needed for a 1-dimensional array # Iterate over 1-dimensional array for row_idx in range(row_max_idx): # Find the index value of each extracted element for y_idx in range(max_y_idx): # Traverse the set of 'slices' of each layer length of the original 2D array, for example: lst = [1, 2, 3, 4] # Then lst [2:] is [3, 4], that is, everything starting from subscript 2; lst [: 2] is [1, 2], that is, before subscript 2 # _pdt is the abbreviation of product, which records the product of the lengths of all layers below the current layer of the original 2D array _pdt = 1 for n in arr_len[y_idx+1:]: _pdt * = n # _offset is the offset, recording the sum of the lengths of all layers above the current layer of the original 2D array _offset = 0 for n in arr_len[:y_idx]: _offset += n # Calculate the element extraction index: divide the current X-axis value by _pdt, then take the remainder from the original 2D array current layer length, and add the offset arr_idx[y_idx] = (row_idx // _pdt) % arr_len[y_idx] + _offset # Traverse the index collection, select elements from the 1-dimensional array and put them in _lst_tmp _lst_tmp = [] for idx in arr_idx: _lst_tmp.append(lst_row[idx]) # Finally, append _lst_tmp as an element to lst_rst lst_rst.append(_lst_tmp) return lst_rst ''' Relatively speaking, the recursive method is more convenient for code reading, and it is more in line with the intuition of thinking; the circular method is more circumvent but relatively unlimited by the number of recursive layers. The following are the two methods for the same data test, you can see that the two lists returned have the same element. ''' if __name__ == "__main__": data = [ [1, 2], [3, 4, 5], [6, 7, 8, 9] ] print('----------------') lst1 = dynloop_loop(data) print(len(lst1)) print(lst1) print('----------------') lst2 = dynloop_rcsn(data) print(len(lst2)) print(lst2) print('----------------') # Return True if two lists have the same element print(lst1 == lst2)
import itertools from dynloop_loop_rcsn import dynloop_loop, dynloop_rcsn if __name__ == "__main__": data = [ [1, 2], [3, 4, 5], [6, 7, 8, 9], [11, 12], [13, 14, 15], [16, 17, 18, 19], [21, 22], [23, 24, 25], [26, 27, 28, 29] ] print('----------------') lst1 = dynloop_loop(data) print(len(lst1)) #print(lst1) print('----------------') lst2 = dynloop_rcsn(data) print(len(lst2)) #print(lst2) print('----------------') lst3 = list(map(list, (itertools.product(*data)))) print(len(lst3)) #print(lst3) print('----------------') print(lst1 == lst2, lst2 == lst3)
/Users/abc/PycharmProjects/testpy/venv/bin/python /Users/abc/PycharmProjects/testpy/test.py
----------------
13824
----------------
13824
----------------
13824
----------------
True True
Process finished with exit code 0