范围的范围到向量的向量
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
现在是执行此操作的惯用方法。
假设我有一个名为 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
现在是执行此操作的惯用方法。