如何使用范围-v3压缩矢量的矢量

How to zip vector of vector with range-v3

本文关键字:压缩 -v3 使用范围      更新时间:2023-10-16

(这是 Sum 向量的后续,范围为 v3(

如果我有两个(或更多(向量,我可以将它们与range-v3一起zip,如下所示:

std::vector< int > v1{1,1,1};
std::vector< int > v2{2,2,2};
auto v = ranges::views::zip( v1, v2 )
| ranges::views::transform( ... );

这很好用,但在实践中,我没有显式向量,但我确实有一个向量向量。我想执行以下操作,但它没有给出相同的结果。(其实我不确定结果是什么,也不知道如何确定结果是什么!


std::vector< std::vector< int > > V{{1,1,1},{2,2,2}};
auto vV = ranges::views::zip( V )
| ranges::views::transform( ... );

我能做些什么来压缩vector< vector >就像压缩一些显式向量一样?我尝试过将joinstridechunk等一起使用,但没有找到神奇的组合。

ranges::views::zip( V )只压缩一个向量,而不是它的内容。(类似于std::make_tuple(v)它确实std::tuple<vector<int>>(。

问题是 vector 具有运行时大小,因此从其内容构建类似tuple需要一些帮助:

template <std::size_t ...Is, typename T>
auto zip_vector(std::index_sequence<Is...>, std::vector<std::vector<T>>& v)
{
assert(N <= v.size());
return ranges::views::zip(v[Is]...);
}
template <std::size_t N, typename T>
auto zip_vector(std::vector<std::vector<T>>& v)
{
return zip_vector(std::make_index_sequence<N>(), v);
}

然后:

std::vector< std::vector< int > > V{{1,1,1},{2,2,2}};
auto vV = zip_vector<2>( V )
| ranges::views::transform( ... );

我想如果你不知道编译时外部vector的大小,剩下的唯一合理的解决方案就是解决它。与其试图zip它,我建议在此基础上使用accumulate,因为在这种情况下它似乎更通用。

std::vector< std::vector< int > > V{{1,1,1},{2,2,2}};
auto vV = ranges::accumulate(
V,
std::vector<ResultType>(V[0].size()),
[](const auto& acc, const auto& next) {
auto range = ranges::views::zip(acc, next) | ranges::views::transform(...);
return std::vector<int>(range.begin(), range.end());
}
)

编辑: 我忘记了必须复制的范围。

根据您链接到的问题,我认为这个特定问题是一个 XY 问题,即除了建立在前面的解决方案之上之外,没有理由让zip来解决这个问题。虽然当范围的数量在编译时已知时zip可能是一种合理的方法,但当数量仅在运行时已知时,它只会妨碍。

因此,鉴于您有一个vector<vector<int>>,与上一个问题类似,所有内部向量的大小都相同,这是我在 range-v3 中编写它的方式:

namespace rv = ranges::views;  
std::vector<std::vector<int>> v{{1,2,3},{4,5,6}};
int n = v.size();
int k = v[0].size();
auto vs = v | rv::join;
auto s = rv::iota(0, n + 1) 
| rv::transform([=](int i){
return ranges::accumulate(
vs | rv::drop(i) | rv::stride(k), 0);
});

这是一个演示。

压缩vector<vector<T>>是您想要做的事情,因为它允许您转置这些范围。

其他答案足以解释为什么你不能zipvector<vector<T>>.

但是,您可以编写一个显式转置适配器,就像 Eric Niebler 在他的演讲中演示 range-v3 所做的那样

  • https://www.youtube.com/watch?v=mFUXNMfaciE
  • https://github.com/ericniebler/range-v3/blob/master/example/calendar.cpp

但是,这是一个昂贵的适配器,昂贵的适配器会被忽略 https://github.com/ericniebler/range-v3/issues/776