如何将一些计算值包装在一个范围内以允许在变换的输出上使用连接?

问题描述

最初的问题

我有一段代码,我通过将 std::vector 分成组并处理每个组来处理它。

if-else 决定了每个组所经历的处理:

  • 选择 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

在某种程度上,我认为,我需要将单个 79,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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...