范围的范围到向量的向量

ranges of ranges to vector of vectors

假设我有一个名为 rng 的 T 范围。我可以

auto groups = ranges::view::group_by(rng, bin_op);

组现在是一系列 T 的范围。

这个我也可以

auto groups = ranges::view::group_by(rng, bin_op) | ranges::to_vector;

获取 T 范围的向量。然而这

auto groups = ranges::view::group_by(rng, bin_op)
            | ranges::to_vector
            | ranges::action::transform([] (auto r) { return r | ranges::to_vector; };

以及

auto groups = ranges::view::group_by(rng, bin_op)
            | ranges::to_vector
            | ranges::action::transform([] (auto r) { return std::vector<T>{} | ranges::action::push_back; };

将无法工作,因为显然 ranges::action::transform() returns 在这种情况下无效并且 "The result type of the function passed to action::transform must be writable back into the source range".

那么如何将范围的范围转换为向量的向量?

注意:抱歉标签不好,但我找不到 ranges/ranges-ts/ranges-v3 标签,我不允许创建标签,也无法在标题中使用它。

假设您使用的是 Rangesv3,我对文档的阅读给了我这样的信息:

auto groups = ranges::view::group_by(rng, bin_op)
        | ranges::view::transform( ranges::to_vector )
        | ranges::to_vector;

或者也许

auto groups = ranges::view::group_by(rng, bin_op)
        | ranges::view::transform( [] (auto r) { return r | ranges::to_vector; } )
        | ranges::to_vector;

(我记得 ranges::to_vector 可以以函数式的方式使用,但我可能错了,或者事情可能已经改变了。第一个假设它可以;第二个假设不是。 )

它所做的是首先将范围的惰性范围转换为向量的惰性范围。

然后它将惰性向量范围转换为向量的向量。

这样效果更好(由内而外),因为中间产品是惰性的 "on the outside"。可能有一种从外到内的方法,但是惰性范围向量 必须实际存在 ,而惰性范围向量不存在。

您可以使用ranges::to将范围的范围转换为向量的向量。例如:

#include <vector>
#include <iostream>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/group_by.hpp>
#include <range/v3/view/transform.hpp>

int main() {
    std::vector<int> rng {0,1,2,3,4,5,6,7,8,9};
    auto groups = ranges::view::group_by(rng, [](int i, int j){
        return j/3 == i/3;
    });

    auto vs = groups | ranges::to<std::vector<std::vector<int>>>;

    // Display the result: [[0,1,2],[3,4,5],[6,7,8],[9]]
    std::cout << ranges::view::transform(vs, ranges::view::all) << std::endl;
}

2020 年 6 月 10 日:以前,此答案建议简单地将 groups 分配给 vector<vector<int>> 变量,因为 range-v3 过去支持从视图到容器的隐式转换。隐式转换是有问题的,因此它们被删除了。 ranges::to 现在是执行此操作的惯用方法。