【问题标题】:Filtered range (circular) traversal starting from iterator over original sequence从原始序列上的迭代器开始的过滤范围(循环)遍历
【发布时间】:2020-04-02 18:42:14
【问题描述】:

假设您有一个容器,并且有一个指向该容器某些元素的迭代器。要求是循环推进该迭代器但使用过滤器。现在,在序列上创建一个过滤(圆形)视图是微不足道的,但是当您拥有的只是原始的迭代器时,您如何启动遍历?我正在考虑连接两个范围,如下所示:

#include <iostream>

#include <range/v3/all.hpp>
using namespace ranges;

int main () {
    std::vector< int > xs{ -4, 1, 3, -4, 2, -3, 6, 7, 8, -9, -10 };

    auto iter = xs.begin ();
    std::advance (iter, 8);

    std::cout << *iter << std::endl;

    auto lhs = make_subrange (iter, xs.end ());
    auto rhs = make_subrange (xs.begin (), iter);

    auto is_pos = [](auto x) { return x >= 0; };
    auto rng = views::cycle (views::concat (lhs, rhs) | views::filter (is_pos));

    auto next = ++rng.begin ();
    std::cout << *next << std::endl;

    return 0;
}

有没有更简单的方法?

【问题讨论】:

    标签: c++ range-v3


    【解决方案1】:

    是的,您可以简单地 drop iter 之前的元素,而不是在 iter 处连接 2 个子范围。

    所以这个sn-p

    auto lhs = make_subrange (iter, xs.end ());
    auto rhs = make_subrange (xs.begin (), iter);
    
    auto rng = views::cycle (views::concat (lhs, rhs) | views::filter (is_pos));
    

    变成

    auto rng = xs | views::cycle
                  | views::drop(distance(xs.begin(), iter))
                  | views::filter(is_pos);
    

    请注意,虽然此解决方案更简单,但它会循环遍历所有未过滤的元素,并多次应用过滤谓词。您的解决方案可能比这个更高效

    【讨论】:

    • 感谢您的建议,但目的是如果不在剩余元素中,在 iter 和 end 之间,然后在 beg 和 iter 之间的元素中找到下一个元素。 IOW,当搜索在容器中间的某个地方开始时,环绕并从头开始。编辑:我误解了你的解决方案。现在我想我明白了。
    猜你喜欢
    • 1970-01-01
    • 2016-01-21
    • 2013-05-03
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2019-03-30
    相关资源
    最近更新 更多