在C ++中迭代具有可变维大小的N维矩阵 [英] Iterating over an N-dimensional matrix with variable dimension sizes in C++

查看:120
本文介绍了在C ++中迭代具有可变维大小的N维矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试遍历n维矩阵,其中矩阵的每个维也具有可变大小。

I am trying to iterate over an n-dimensional matrix where each dimension of the matrix also has a variable size.

我特别希望每个元素都具有多个尺寸坐标,就像 for循环一样,为您提供 i 来访问数组中的元素。

I specifically want to have each elements multi-dimensional coordinate, like a for loop gives you i to access an element in an array.

我想基本上重新创建一个嵌套的for循环,如带有递归的以下代码,在其中我可以将任何其他类型的数字放入 dimensionSize

I want to basically re-create a nested for loop like the following code with recursion where I could put any different kind of numbers into dimensionSize.

std::vector<int> dimensionSize = {1, 4, 4};

for (int i = 0; i < dimensionSize [0]; i++)
{
    for (int j = 0; j < dimensionSize [1]; j++)
    {
        for (int k = 0; k < dimensionSize [2]; k++)
        {
            std::cout << i << " " << j << " " << k << std::endl;
        }
    }
}

此嵌套循环的结果是...

The results of this nested loop are...

0 0 0
0 0 1
0 0 2
0 0 3
0 1 0
0 1 1
0 1 2
0 1 3
0 2 0
0 2 1
0 2 2
0 2 3
0 3 0
0 3 1
0 3 2
0 3 3

到目前为止,我在C ++中遍历n维矩阵时发现的所有示例/解决方案都是非常凌乱的代码,对于固定尺寸尺寸,例如9x9x9或3x3x3。

So far all of the examples/solutions I've found on traversing n-dimensional matrices in C++ have been really messy code and also for fixed dimension sizes e.g. 9x9x9 or 3x3x3.

但是我的矩阵可能是1x256x513x3或各种尺寸。

However my matrix could be 1x256x513x3 or all kinds of sizes.

我目前拥有以下功能接近我想要的功能,但是它有一个问题。

I currently have the following function which is close to getting what I want however it's got one problem.

void iterate_over_n_dimensions (std::vector<int>& counters,
                                std::vector<int> dimensionSizes, 
                                int currentDimension)
{
    for (long i = 0; i < dimensionSizes [currentDimension]; i++)
    {
        print_counter (counters);

        if (currentDimension + 1 != dimensionSizes.size())
        {
            iterate_over_n_dimensions (counters, 
                                       dimensionSizes, 
                                       currentDimension + 1);
        }

        counters [currentDimension] ++;
        counters [currentDimension] %= dimensionSizes [currentDimension];
    }
}

运行以下命令...

int main(int argc, const char * argv[])
{
    std::vector<int> dimensionSizes = {1, 4, 4};
    std::vector<int> counters(dimensionSizes.size(), 0);

    iterate_over_n_dimensions (counters, dimensionSizes, 0);

    return 0;
}

此递归函数的结果是...

The results of this recursive function are...

0 0 0 
0 0 0 
0 0 0 
0 0 1 
0 0 2 
0 0 3 
0 1 0 
0 1 0 
0 1 1 
0 1 2 
0 1 3 
0 2 0 
0 2 0 
0 2 1 
0 2 2 
0 2 3 
0 3 0 
0 3 0 
0 3 1 
0 3 2 
0 3 3 

您可以看到,输出每当嵌套的for循环完成时,重复一次! ...

You can see, the output repeats itself every time a nested for loop is completed! The repetitions at...

0 1 0 
0 2 0 
0 3 0 

我添加的尺寸越大,这个问题就越严重。
例如,每完成一次4x4x4循环,就会重复生成一个1x4x4x2矩阵,并在其他地方重复出现。

This problem gets worse the more dimensions I add. For examples a matrix of 1x4x4x2 repeats every time it completes it's 4th dimensional loop and more in other places.

如果有人可以提出一种简洁的解决方案

If anyone could suggest a solution that is as cleanly written as my current function I would really appreciate it!

现在,我将不得不实现一个带有大量for循环的大型switch语句,并限制其数量。尺寸大约在5左右。

Right now I'm going to have to implement a massive switch statement with lots of for loops and capping the number of dimensions at 5 or so.

推荐答案

如果我正确理解,则希望迭代 n维矩阵的所有元素(实际上不称为矩阵),并且需要一种获取所有索引的方法。我将从以下内容开始:

If I understand correctly you want to iterate all elements of the "n-dimensional matrix" (actually not called "matrix") and need a way to get all indices. I would start with something like this:

#include <iostream>
#include <vector>

struct multi_index {
    std::vector<size_t> dimensions;
    std::vector<size_t> current;
    multi_index(std::vector<size_t> dim) : dimensions(dim), current(dim.size()) {}
    void print() {
        for (const auto& e : current) std::cout << e << " ";
        std::cout << "\n";
    }
    bool increment() {        
        for (size_t i=0;i<dimensions.size();++i) {
            current[i] += 1;
            if (current[i] >= dimensions[i]) {
                current[i] = 0;
            } else {
                return true;
            }
        }
        return false;
    }
};


int main() {
    multi_index x{{1,2,3}};
    do {
        x.print();
    } while (x.increment());    
}

,然后使其适应特定需求。例如,向量可能是 std :: array s并依赖于实际容器,您可能想要一种简单的方法来访问容器中的元素而不必编写 data [x [0]] [x [1]] [x [2]]

And then adpapt it to the specific needs. Eg the vectors could probably be std::arrays and depening on the actual container you probably want an easy way to access the element in the container without having to write data[ x[0] ][ x[1] ][ x[2] ].

通常,最好将数据展平为一维数据结构,然后仅映射索引。特别是当尺寸固定时,您可以从数据局部性中受益。上面的代码使您可以编写一个循环遍历所有维度的循环,然后需要反向映射,即将许多索引映射为平面索引。以下内容尚未经过全面测试,只是概述了这一点:

Note that often it is better to flatten the data into a one dimensional data structure and then just map the indices. Especially when the dimensions are fixed you can benefit from data locality. While the above lets you write a single loop to iterate through all dimensions you then need the reverse mapping, ie many indices to a flat index. The following is not thoroughly tested, but just to outline the idea:

#include <vector>
#include <utility>
template <typename T>
struct multi_dim_array {
    std::vector<T> data;
    std::vector<size_t> dimensions;
    multi_dim_array(std::vector<size_t> dim) {
        size_t total = 1;
        for (const auto& d : dim) total *= d;
        data.resize(total);
    }
    T& get(std::initializer_list<int> index) {
        return data[flatten_index(index)];
    }
    size_t flatten_index(std::initializer_list<int> index) {
        size_t flat = 0;
        size_t sub_size = 1;
        for (auto x = std::make_pair(0u,index.begin());
             x.first < dimensions.size() && x.second != index.end();
             ++x.first, ++x.second) {
            flat += (*x.second) * sub_size;
            sub_size *= dimensions[x.first];
        }
        return flat;
    }
};
int main(){
    multi_dim_array<int> x{{2,2,3}};
    x.get({1,1,1}) = 5;
}

将多维数据存储在平面数组/向量中并编写简单循环

Once you store the multidimensional data in a flat array/vector writing a simple loop to iterate all elements should be straightforward.

PS:说实话,我没有费心在代码中找到问题,递归让我头晕:P

PS: to be honest I didn't bother to find the problem in your code, recursion makes me dizzy :P

这篇关于在C ++中迭代具有可变维大小的N维矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆