【问题标题】:Iterating over a range of ranges [duplicate]迭代一系列范围[重复]
【发布时间】:2012-11-27 06:36:16
【问题描述】:

如果我有一个范围范围,有没有办法将它们连接在一起并像它们是一个范围一样迭代它们?

我所说的范围是指任何类型的容器或迭代器对。基本上就像 boost 的ranges。 Boost 已经有一个函数可以将两个范围与 boost::join 连接在一起,但该函数不能连接任意数量的范围。

基本上,我正在寻找一种方法来执行many 函数在这段代码中所做的事情:

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

将输出 0、1、2、3。

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

【问题讨论】:

  • 我想你必须用一个迭代器来定义你自己的向量子类,它可以满足你的需求。据我所知,没有内置的单线。
  • 嵌套循环不够吗? for(auto&amp; i : o) for(auto&amp; e : i) /* do stuff */
  • @Xeo 不,因为我必须对其进行一些转换并将其作为另一个范围(即迭代器对)返回。我想我只是重组程序,而不是再追究这个问题。

标签: c++ boost c++11


【解决方案1】:

这是一个扁平化迭代器的示例,它与基于范围的 for 一起使用(取自 here 并添加 boost::make_iterator_range 以显示范围版本)(但仍需要工作):

#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

【讨论】:

    猜你喜欢
    • 2019-03-14
    • 2014-01-16
    • 2011-10-28
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 2017-01-16
    相关资源
    最近更新 更多