展平 n 维向量
Flatten n-dimensional vector
我制定了一个可以递归使用的算法,它以非递归的方式工作,但是,我无法以递归形式对其进行测试,因为我无法从模板创建 n-1 维变量。
为了帮助,我写下了变量名称及其含义:
v
:n维向量dims
:n个长向量,每个维度(例如:如果它是一个看起来像int x[3][6][4]
的数组,那么dims
看起来像:{3,6,4})p
:尺寸的乘积,用于获取平面向量的大小(例如:3*6*4)ret
:返回的平面向量sub_dims
: 与没有第一维dims
execpt 相同(例如:{6, 4})sub_p
: 与p
相同,但没有第一个因子(例如:6*4)sub_ret
:n-1维向量的返回平面向量
代码:
template <typename T>
vector<int> dim_flat(vector<T> v, vector<int> dims)
{
// creating variables and vectors
int n = dims.size();
int p = dims[0];
for (int i = 1; i < n; i++)
{
p *= dims[i];
}
int sub_p = p / dims[0];
vector<int> sub_dims;
sub_dims.assign(dims.begin() + 1, dims.end());
vector<int> ret(p);
// algorithm
if (n > 1)
{
for (int i = 0; i < dims[0]; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
for (int j = 0; j < sub_p; j++)
{
ret[i * sub_p + j] = sub_ret[j];
}
}
}
else
{
// case for the input is 1D
// not yet written
}
return ret;
}
使用此代码,项目构建,但是如果我在main中调用它:
vector<int> ret = dim_flat(v, dims);
其中v
是例如 4D 向量,dims
是包含 {3, 3, 3, 3} 的向量,那么我在尝试构建时得到以下结果:
error C2784: 'std::vector<_Ty> dim_flat(std::vector<T>,std::vector<_Ty>)' : could not deduce template argument for 'std::vector<T>' from 'int'
对于生产线
vector<int> sub_ret = dim_flat(v[i], sub_dims);
我有点(但不是真的)理解此错误的含义,所以我希望同样的事情会发生,它确实如此:
T x = v[i];
vector<int> sub_ret = dim_flat(x, sub_dims);
这是我不再真正理解错误的部分,因为我认为通过参数vector<T> v
我指定输入(例如 4D 矢量)将被理解为T
的向量,其中T
是一个 3D 向量,也可以索引,因为它是vector<T>
。所以按照这个逻辑,我认为如果我给递归的第一个T
是 3D 向量,那么更深入的这个 3D 向量现在将被理解为T'
向量,其中T'
是 2D 向量,依此类推。
显然,要么我的逻辑有缺陷,要么我使用了错误的方法(或两者兼而有之),所以问题是:我该如何解决/解决这个问题?
编辑:
归功于Max66的解决方案。
代码可能可以更优化,但至少现在它可以工作。
法典:
//// for integer only
// case input is 0-dimensional (simply a variable)
template <typename T>
vector<int> dim_flat (const T &v, const vector<int> &dims)
{
return vector<int>(1, v);
}
// case input is n-dimensional
template <typename T>
vector<int> dim_flat(const vector<T> &v, const vector<int> &dims)
{
// creating variables and vectors
int n = dims.size();
int p = dims[0];
for (int i = 1; i < n; i++)
{
p *= dims[i];
}
int sub_p = p / dims[0];
vector<int> sub_dims;
sub_dims.assign(dims.begin() + 1, dims.end());
vector<int> ret(p);
// algorithm
if (n > 1) // case n-dimensional
{
for (int i = 0; i < dims[0]; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
for (int j = 0; j < sub_p; j++)
{
ret[i * sub_p + j] = sub_ret[j];
}
}
}
else // case 1-dimensional
{
for (int i = 0; i < p; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
ret[i] = sub_ret[0];
}
}
return ret;
}
简短回答:添加函数
std::vector<int> dim_flat (int v, std::vector<int> const &)
{ return {v}; }
如果您可以使用 C++11 或更高版本,或者
std::vector<int> dim_flat (int v, std::vector<int> const &)
{ return std::vector<int>(1, v); }
如果您必须使用 C++98
长答案:如果我没错的话,问题是,当你用std::vector<int>
调用dim_flat()
时(当T
int
时),你有n == 1
,所以dim_flat()
不会被调用(执行"输入 1D 的大小写"),但编译器不是那么聪明,无法理解没有必要用int
调用dim_flat()
(而不是std::vector<T>
),所以寻找dim_flat(int, std::vector<int>)
并没有找到它。
因此,为了使编译器满意,您必须实现dim_flat(int, std::vector<int>)
。
可以是一个虚拟函数(返回一个空向量),但我建议你正确实现它。
一点主题:请避免使用无用的向量副本;在您的dim_flat()
中,v
和dims
只被读取,不被修改;所以你可以将它们作为常量引用接收,如下所示
template <typename T>
std::vector<int> dim_flat(std::vector<T> const & v,
std::vector<int> const & dims)
PS:你为什么不简单地写如下?
std::vector<int> dim_flat (std::vector<int> const & v)
{ return v; }
template <typename T>
std::vector<int> dim_flat(std::vector<std::vector<T>> const & v)
{
std::vector<int> ret;
for ( auto const & e : v )
{
auto s = dim_flat(e);
ret.reserve( ret.size() + s.size() );
ret.insert( ret.end(), s.cbegin(), s.cend() );
}
return ret;
}
- 写入向量<向量<bool>>
- 函数向量_指针有不同的原型,我可以构建一个吗
- std::向量与传递值的动态数组
- 将值指定给向量(2D)的向量中的某个位置
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 如何将三维尺寸不固定的三维阵列展平为一维阵列
- 将展平矩阵乘以向量
- 用于展平矢量向量的 c++ 模板函数
- 隔离位并展平它们
- 有效地展平结构数组
- 如何在 c++ 中展平字典
- 展平C++结构
- 在 cuda 中将 3D 阵列展平为 1D
- 展平 n 维向量
- 如何使用可变参数模板来展平类型树
- CUDA:是将 M[][] 用于 2D 静态数组还是将它们展平为 M[] 更好
- 展平/重构C++某些输入的模板源
- 将子向量合并/展平为单个向量c++(将2d转换为1d)
- <CString> 使用 C++ / STL 将 std::vector 展平为multi_sz的推荐方法是什么
- 用于展平容器容器的泛型函数