遍历一系列范围 [英] Iterating over a range of ranges

查看:199
本文介绍了遍历一系列范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一系列的范围,是有办法一起加入他们的行列,并遍历他们,如果他们是一个单一的范围是多少?

If I have a range of ranges, is there a way to join them together and iterate over them as if they were a single range?

按范围,我的意思是任何类型的容器或迭代器对。基本上像升压的范围。提升已经具备了功能与增强连接两个范围::一起加入,但该功能不能加入范围的arbitary数量。

By range, I mean any kind of container or iterator pair. Basically like boost's ranges. Boost already have a function for joining two ranges together with boost::join, but that function can't join an arbitary number of ranges.

基本上,我正在寻找一个方式做什么的函数确实在这片code的:

Basically, I'm looking for a way to do what the the many function does in this piece of code:

std::vector<std::vector<int>> n = {{0, 1}, {2, 3}};
for (auto i : many(n))
    std::cout << i << '\n';

其中将输出0,1,2,3

Which would output 0, 1, 2, 3.

在C#中,我有的SelectMany 这可能做到这一点。

In C#, I had SelectMany which could do this.

推荐答案

下面是与基于范围(摘自<二手不上不下迭代器的例子href=\"http://stackoverflow.com/questions/11783541/c-iterator-adapter-over-collection-of-vectors?lq=1\">here并加入的boost :: make_iterator_range 显示范围版)(仍需要工作虽然):

Here is an example of a flattening iterator used with range-based for (taken from here and added boost::make_iterator_range to show range version) (still needs work though):

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/range.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <utility>

template <typename Iter>
class flattening_iterator :
    public boost::iterator_adaptor<
                flattening_iterator<Iter>,
                Iter,
                typename Iter::value_type::iterator::value_type,
                boost::forward_traversal_tag,
                typename Iter::value_type::iterator::value_type
    >
{
private:
        using super_t = boost::iterator_adaptor<
                                flattening_iterator<Iter>,
                                Iter,
                                typename Iter::value_type::iterator::value_type,
                                boost::forward_traversal_tag,
                                typename Iter::value_type::iterator::value_type
                        >;
        using inner_iterator = typename Iter::value_type::iterator;
public:
        flattening_iterator(Iter it)
                : super_t(it),
                  inner_begin(),
                  inner_end(),
                  outer_end(it)
        {}
        flattening_iterator(Iter begin, Iter end)
                : super_t(begin),
                  inner_begin((*begin).begin()),
                  inner_end((*begin).end()),
                  outer_end(end)
        {}
    using value_type = typename Iter::value_type::iterator::value_type;
private:
    friend class boost::iterator_core_access;
    inner_iterator inner_begin;
    inner_iterator inner_end;
    Iter outer_end;

    void increment()
    {
        if (this->base_reference() == outer_end)
            return; // At the end

        ++inner_begin;
        if (inner_begin == inner_end)
        {
            ++this->base_reference();
            inner_begin = (*this->base_reference()).begin();
            inner_end = (*this->base_reference()).end();
        }
    }

    value_type dereference() const
    {
        return *inner_begin;
    }
};

template <typename Iter>
auto flat_iter(Iter it) -> flattening_iterator<Iter>
{
    return flattening_iterator<Iter>(it);
}

template <typename Iter>
auto flat_iter(Iter begin, Iter end) -> flattening_iterator<Iter>
{
    return flattening_iterator<Iter>(begin, end);
}

template <typename Cont>
auto flatten(Cont& c) -> boost::iterator_range<flattening_iterator<decltype(std::declval<Cont>().begin())>>
{
    return boost::make_iterator_range(flat_iter(c.begin(), c.end()), flat_iter(c.end()));
}


int main()
{
    std::vector<std::vector<int>> v1{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    for (auto i : flatten(v1))
    {
        std::cout << i << ' ';
    }
}

输出

1 2 3 4 5 6 7 8 9

1 2 3 4 5 6 7 8 9

这篇关于遍历一系列范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆