问题描述
最初的问题
我有一段代码,我通过将 std::vector
分成组并处理每个组来处理它。
if
-else
决定了每个组所经历的处理:
这是代码的简化:
#include <range/v3/view/group_by.hpp>
#include <vector>
namespace rv = ranges::views;
auto f1 = [](auto){ return 7; /* this actually does depend on the input */ };
auto f2 = [](auto){ return 9; /* this actually does depend on the input */ };
auto f3 = [](auto){ return 5; /* this actually does depend on the input */ };
auto f4 = [](auto){ return 8; /* this actually does depend on the input */ };
int main() {
// input
std::vector<int> v{1,1,3,2,2};
// prepare output
std::vector<int> w; // and resize appropriately
// populate w in a loop
for (auto g : v | rv::group_by(std::equal_to<>{})) {
if (g.front() != 3) {
// for these groups only one item is stored into w
w.push_back(f1(g));
} else {
// for these groups several items are stored into w
w.push_back(f2(g));
w.push_back(f3(g));
w.push_back(f4(g));
}
}
}
我不禁想到,毕竟我只是在做 monadic 绑定,即
- 逐组转换
group_by
的输出, - 每个组可以导致
- 几个元素的序列(
else
分支) - 单个元素(
if
分支),可以理解为单元素序列
- 几个元素的序列(
- 加入序列
因此,我很想将代码简化如下:
#include <range/v3/view/join.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/group_by.hpp>
#include <vector>
namespace rv = ranges::views;
auto f = [](auto x){
auto one = std::vector<int>{7};
auto many = std::vector<int>{9,5,8};
return (x.front() != 3) ? one
: many;
};
int main() {
std::vector<int> v{1,2};
auto w = v | rv::group_by(std::equal_to<>{})
| rv::transform(f)
| rv::join;
}
但是,此代码不起作用,因为 f
不是返回每个组的视图,而是返回真实的 std::vector
。
在某种程度上,我认为,我需要将单个 7
和 9,8
包装到一个范围内,以便 join
能够完成它的工作。
我该怎么做?
一段时间后更新
事实是我点击了 The Surprising Limitations of C++ Ranges Beyond Trivial Cases。
但是,在那篇文章中,SO 上有一个指向 this answer 的链接,这确实也是我问题的答案,其中包括更改此内容
auto w = v | rv::group_by(std::equal_to<>{})
| rv::transform(f)
| rv::join;
到这里
auto w = v | rv::group_by(std::equal_to<>{})
| rv::transform(f)
| rv::cache1
| rv::join;
其中 cache1
缓存 transform
的结果,从而防止 join
在临时 std::vector
消失后存储悬空引用。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)