如何结合范围v3转换,联接和循环?

时间:2019-12-26 23:01:20

标签: c++ c++17 range-v3

我正在尝试使用range-v3库生成无限范围的整数。我的目标是拥有{0,0,0,1,1,1,2,2,2,0,0,0,1,1,1 ...}。 我希望每个数字重复的次数也是可变的。没有这个限制,我可以做到,而且效果很好。

const std::vector<std::vector<int>> repvec = { {0,0,0},{1,1,1},{2,2,2} };
auto joinedVec = repvec | ranges::view::join;
auto infiniteVec = joinedVec | ranges::view::cycle;

但是,如果我想要可变的重复次数,则无法编译:

int nbRep = 3;
const std::vector<int> origVec = { 0, 1, 2 };
auto repVec = origVec | ranges::view::transform( [nbRep] (const int &x) { 
    return ranges::view::repeat(x) | ranges::views::take(nbRep); 
});
auto joinedVec = repVec | ranges::view::join;
auto infiniteVec = joinedVec | ranges::view::cycle;

我不确定这是否是Ranges库的限制或我做错了什么。

1 个答案:

答案 0 :(得分:2)

我真的不明白为什么要这么做:

ranges::view::repeat(x) | ranges::views::take(nbRep)

而不只是:

ranges::view::repeat_n(nbRep)

解决方案非常简单:

auto generate_range(const std::vector<int>& original, const std::size_t reps) {
    using namespace ranges; 

    auto rng = original | views::transform([reps](const auto arg) {
        return views::repeat_n(arg, reps);
    });

    return rng | views::cycle | views::join;
}

我们首先根据original向量创建一个范围范围-我们将其元素转化成重复元素的 range 。我们最后得到一个范围,该元素是由重复值组成的范围。根据您的示例,我们有:

rng = [[0, 0, 0], [1, 1, 1], [2, 2, 2]]

现在,我们只需要循环所有元素。我们最终得到:

rng | cycle = [[0, 0, 0], [1, 1, 1], [2, 2, 2], [0, 0, 0], [1, 1, 1], ...]

我们最后要做的是join

rng | cycle | join = [0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, ...]

完整示例:

#include <iostream>
#include <range/v3/all.hpp>
#include <vector>

auto generate_range(const std::vector<int>& original, const std::size_t reps) {
    using namespace ranges;

    auto rng = original | views::transform([reps](const auto arg) {
        return views::repeat_n(arg, reps);
    });

    return rng | views::cycle | views::join;
}

int main() {
    using namespace ranges;

    const std::vector<int> original = {0, 1, 2};
    const int reps = 3;

    for (const auto r : generate_range(original, reps) | ranges::views::take(15)) {
        std::cout << r << ' ';
    }
}

其中显示:0 0 0 1 1 1 2 2 2 0 0 0 1 1 1