【问题标题】:How to iterate over n dimensions?如何迭代n维?
【发布时间】:2012-12-11 23:48:54
【问题描述】:

在给定维数和每个变量的大小的情况下,如何迭代 n 维数组?

int n;
int size[n];

由于维数不固定,我无法为每个维写一个嵌套循环。我需要代码来处理每个维度的数量。

此外,实际数据存储在 n 维数组或包含大行中所有数据的平面数组中并不重要。两者都可以接受。

int data[16][42][14];   // n-dimensional array
int data[16 * 42 * 14]; // flat array containing the same data

【问题讨论】:

  • 你想用这些n-dimensions做什么?我想你需要知道这一点,因此你也知道维度的数量......
  • 维数不同,你说?这似乎很难解决,因为您需要知道维度的数量才能知道下面每个维度的大小。我没试过,但我想你可以写一些可怕的递归代码来做到这一点......
  • 维度的数量不同,但每个维度的大小是已知的。
  • “遍历数组”是什么意思?看看每个元素?查看每个元素及其索引?或者,就像阿米特的回答一样,只是遍历所有索引向量?如果是第一个,您可以迭代平面数组,首先将平面大小计算为 size[] 数组的乘积。

标签: arrays algorithm loops dimension


【解决方案1】:

Python 代码:

def nd_range(start, stop, dims):
  if not dims:
    yield ()
    return
  for outer in nd_range(start, stop, dims - 1):
    for inner in range(start, stop):
      yield outer + (inner,)

例子:

print(list(nd_range(0, 3, 3)))

[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2 ), (0, 2, 0), (0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2 , 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2 , 0), (2, 2, 1), (2, 2, 2)]

【讨论】:

    【解决方案2】:

    这是我在 MATLAB 中使用递归的方法:

    function out=iterate(data,func,dim)
    % Usage: out=iterate(data,func)
    % This function individually applies the user defined function 'func' to 
    % every element of the array 'data'.
    % The third input 'dim' is for internal recursive use only, after global 
    % setup variables have been initialized.
    
    
    global sz inds g_out
    % 'sz' is size(data) with singleton dimensions removed
    % 'inds' is an array of size [1 length(sz)] containing the current indices
    % 'g_out' is where parts of the output are accumulated throughout iteration
    
    if nargin<3
        %Setup 'inds' 'sz' 'g_out'
        dim=1;  %'dim' is the current dimension to iterate through
        sz=size(data);
        if sz(2)==1
            sz=sz(1);
        end
        inds=ones(1,length(sz));
    
        %Initialize the output as the proper class
        %Depends on the output of the user given function
        switch class(func(data(1)))
            case 'logical'
                g_out= false(sz);
            case 'double'
                g_out=double(zeros(sz));
            case 'char'
                g_out=repmat(' ',sz);
            otherwise
                g_out=cast(zeros(sz),class(func(data(1)))); %#ok<ZEROLIKE>
        end
    end
    
    for i=1:sz(dim)
        inds(dim)=i;
        ndx=subs2ind(sz,inds);
        if dim<length(sz)
            iterate(data,func,dim+1);
        else
            g_out(ndx)=func(data(ndx));
        end
    end
    out=g_out;
    end
    

    【讨论】:

      【解决方案3】:

      您可以使用递归,为每个维度“猜测”其索引并递归调用一个较小的问题,类似于(伪代码):

      iterate(d,n,size,res):
         if (d >= n): //stop clause
             print res
             return
         for each i from 0 to size[d]:
             res.append(i) //append the "guess" for this dimension
             iterate(d+1,n,size,res)
             res.removeLast //clean up environment before next iteration
      

      地点:

      • d 是当前访问的维度
      • size,n 是输入
      • res 是表示当前部分结果的向量

      使用iterate(0,n,size,res) 调用,其中res 被初始化为一个空列表。


      C++ 代码应该是这样的:

      void iterate(int d,int n,int size[], int res[]) {
          if (d >= n) { //stop clause
             print(res,n);
             return;
         }
         for (int i = 0; i < size[d]; i++) { 
             res[d] = i;
             iterate(d+1,n,size,res);
         }
      }
      

      完整的代码和一个简单的例子可以在ideone获得

      【讨论】:

      • 很棒的伪代码。我很想看看你如何翻译 size[n] 平面数组 tho' - 我正要提出类似的建议,但懒得做平面到多维数组的转换。
      • 使用 C++,您可能可以使用模板进行递归编译时(而不是运行时)。但是,这要求您现在也在编译时确定维数。
      【解决方案4】:

      你可以使用递归。这是嵌套数组的伪代码解决方案:

      iterate_n(array, n)
          if n == 0
              do something with the element
          else
              for ary in array
                  iterate_n(ary, n-1)
              end_for
          end_if
      end
      

      【讨论】:

        猜你喜欢
        • 2013-04-03
        • 2018-01-26
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 2014-03-26
        • 2019-06-14
        • 2018-10-09
        • 2012-05-03
        相关资源
        最近更新 更多