在 C++ 中展平多维向量

D. *_*CAR 1 c++ vector multidimensional-array

我想用 C++ 编写一个通用函数来展平所提供的任何多维向量。该方法的签名如下:

template <class U, class T>
void flatten(U* out, T& inp, int* dims, int n){
  // out is the flattened output
  // inp is some multidimensional vector<vector...<U>>
  // dims is an array of the dimensions of inp
  // n is the number of dimensions of inp
  int ticker[n];
  int prodLimit = 1;
  int prod = 0;
  
  // calculate prodLimit as product of elements in dims and initialize ticker
  for (int i=0; i<n; i++){
    ticker[i] = 0;
    prodLimit *= dims[i];
  }
  
  while (prod < prodLimit){
    
    // access the current element in inp
    {...}

    // update ticker
    for (int i=n-1; i>0; i++){
      if (ticker[i] == dims[i]){
        ticker[i] == 0;
        ticker[i-1] += 1;
      }
    }
    prod += 1;
    out[prod] = correctElementIn_inp;
  }
}
Run Code Online (Sandbox Code Playgroud)

除了访问多维向量的特定分量之外,大多数操作都是直接的inp。由于维度是先验未知的,我n在 while 循环中创建一个大小的数组来处理每个维度的计数器并正确更新它。现在剩下的唯一问题是使用代码来访问向量中的正确元素。

举个例子,假设以下内容成立:

#include <vector>

typedef std::vector<std::vector<double>> vec2;
typedef std::vector<std::vector<std::vector<double>>> vec3;

int main(){
  vec2 inp1 = {...};
  vec3 inp2 = {...};
  
  int s1[2] = {2,3};
  int s2[3] = {2,3,4};
  ...

}

Run Code Online (Sandbox Code Playgroud)

现在这个方法应该能够处理inp1inp2。有没有一种方法可以递归访问向量元素,而无需针对每种情况显式使用向量元素访问运算符。

for*_*818 6

由于手动管理内存并手动传递大小,您的代码不必要地复杂。当您使用 时,两者都已过时std::vector。即使您确实想要原始 C 数组作为结果,您仍然可以使用 a std::vector,然后将其内容复制到正确分配的 C 数组。我会使用递归方法:

#include <vector>
#include <iostream>

template <typename E,typename X>
void unroll(const std::vector<E>& v,std::vector<X>& out){
    std::cout << "unroll vector\n";
    out.insert(out.end(), v.begin(), v.end());
}


template <typename V,typename X>
void unroll(const std::vector<std::vector<V>>& v,std::vector<X>& out) {
    std::cout << "unroll vector of vectors\n";
    for (const auto& e : v) unroll(e,out);
}


int main() {
    std::vector<std::vector<std::vector<int>>> x;
    std::vector<int> y;
    x.push_back({{1,2,3},{4,5,6}});
    x.push_back({{7,8,9}});
    unroll(x,y);
    for (const auto& e : y) std::cout << e << " ";
}
Run Code Online (Sandbox Code Playgroud)

输出

unroll vector of vectors
unroll vector of vectors
unroll vector
unroll vector
unroll vector of vectors
unroll vector
1 2 3 4 5 6 7 8 9 
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以递归访问向量元素,而无需针对每种情况显式使用向量元素访问运算符。

向量元素存储在连续的内存中,因此您可以通过其使用指针算术data()。然而, astd::vector<std::vector<int>>并不将ints 存储在连续的内存中。只有内部向量元素是连续存储的,而每个内部向量在堆“某处”分配元素。x[0][0][0]不访问就没有访问的捷径x[0][0]。实际上,我建议您重新考虑是否要首先使用嵌套向量。


PS:我有点作弊;)。我希望在将out元素推入其中之前先计算总大小,就像在代码中所做的那样,性能会更高。为了简洁起见,上面省略了它。可以通过与上面代码类似的递归来完成。您不会继续进行操作,而是out会积累一些,size直到到达第一个非向量元素类型。然后为out前期预留足够的空间,然后才运行填充的实际递归out