简体   繁体   English

如何用步幅遍历n维数组

[英]how to traverse an n-dimensional array with stride

I have an indexing issue that I am trying to solve. 我有一个索引问题,我试图解决。 I have a n-dimensional array with known shape. 我有一个已知形状的n维阵列。 I would like to traverse the array with a stride (possibly different in each dim). 我想以一个步幅(每个暗淡可能不同)遍历数组。

With fixed dimensions, I would do this with nested for loops (small arrays) and increment by the stride: 对于固定的维度,我会使用嵌套for循环(小数组)并按步幅递增:

std::vector<int> shape = {10, 10}; // h,w
int num_dim = shape.size();
std::vector<int> stride = {1,2};

for (int i = 0; i< shape[0]; i+=stride[0]) {
    for (int j = 0; j< shape[1]; j+=stride[1]) {
     //print flattened index (row major)
     printf("index: %d\n",i*shape[0]+j);
    }

}

But how would I do this with an n-dimensional array (flattened)? 但是我如何使用n维数组(展平)呢? Ie something like: 就像这样:

std::vector<int> shape = {10, 10}; // h,w
int num_dim = shape.size();
std::vector<int> stride = {1,2};

int shape_size = 1;
for (int i = 0; i< num_dim; ++i) {
shape_size *= shape[i];
}

int ind = 0;
while (ind < shape_size) {
 // somehow incr ind by the correct amount according to stride, and shape
 // or check if the ind is in the stride (less desirable)
}
class Foo {
public:
    std::vector<int> shape = { 10, 10 }; // h,w
    std::vector<int> stride = { 1, 2 };
    std::vector<int> d = { 0, 0 };
    bool add_end = false;
    void AddStride(int index) {
        d[index] += stride[index];
        if (d[index] < shape[index]) {
            return;
        } else {
            if (index == 0) {
                add_end = true;
                return;
            }
            d[index] = 0;
            index--;
            AddStride(index);
        }
    }
    bool AddStride() {
        AddStride(d.size() - 1);
    }
};
int main() {
    Foo f;
    while(f.add_end != true) {
        //do something
        f.AddStride();
    }
}
class Traverse {
private:
    unsigned m_numDim;
    std::vector<unsigned int> m_vShape;
    std::map<unsigned int, unsigned int> m_mStrides;

public:
    Traverse( const std::vector<unsigned int>& shape, const std::vector<unsigned int>& strides );
    std::vector<unsigned int>& traverse();
}; // Traverse

// ---------------------------------------------------------------
// Traverse()
Traverse::Traverse( const std::vector<unsigned int>& shape, const std::vector<unsigned int>& strides ) {
    if ( shape.empty() || strides.empty() ) {
       return;
    }
    m_vShape = shape;
    m_numDim = m_vShape.size();

    // Here Use The Passed In Vector Of Known Strides To Create Your Map As      
    // An Association For Each Dimension With Its Stride
    for ( unsigned index = 0; index < strides.size(); index++ ) {
        m_mStrides[index+1] = strides[index];
    }         
} // Traverse

// ----------------------------------------------------------------
// traverse()
std::vector<unsigned int>& Traverse::traverse() {
    std::vector<unsigned int> vTemp;

    for ( unsigned index = 0; index < m_numDim; ++index ) {
        // Use Your Map Against Your Stored Shape Vector To Do The Traversing.
    }

    return vTemp; // Or m_vShape;
} // traverse

Here m_mStrides is easy to work with knowing that m_mStrides.first = Which Dimension and m_mStrides.second = The Stride in that Dimension. 在这里,m_mStrides很容易知道m_mStrides.first =哪个Dimension和m_mStrides.second =该Dimension中的Stride。

This is not a complete working class but just an illustration to get you started. 这不是一个完整的工人阶级,只是一个让你入门的插图。 I also choose to use unsigned int rather then ints because when dealing with shape's sizes, dimensions and strides negative numbers doesn't make sense, however if you are using existing code that is already preformatted using int would be okay, but I would suggest doing error or bounds checking for negatives. 我也选择使用unsigned int而不是int,因为在处理shape的大小时,尺寸和步幅负数没有意义,但是如果你使用已经使用int预先格式化的现有代码就可以了,但我建议你这样做错误或边界检查否定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM