如何用步幅遍历n维数组

时间:2015-05-06 00:18:01

标签: c++ arrays algorithm

我有一个索引问题,我正在尝试解决。 我有一个已知形状的n维阵列。 我想用一个步幅遍历数组(每个暗淡可能不同)。

对于固定尺寸,我会使用嵌套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);
    }

}

但是我如何使用n维数组(展平)呢? 即类似的东西:

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)
}

3 个答案:

答案 0 :(得分:0)

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();
    }
}

答案 1 :(得分:0)

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

这里m_mStrides很容易知道m_mStrides.first =哪个Dimension和m_mStrides.second =该Dimension中的Stride。

这不是一个完整的工人阶级,只是一个让你入门的插图。我也选择使用unsigned int而不是int,因为在处理shape的大小时,尺寸和步幅负数都没有意义,但是如果你使用已经使用int预先格式化的现有代码就可以了,但我建议做错误或边界检查否定。

答案 2 :(得分:0)

这是一篇很好的文章解释它:https://ajcr.net/stride-guide-part-1/ 阅读关于 n 维步幅的第 2 部分以及文章的第 2 部分(在第 1 部分顶部找到链接)