如何迭代矢量地图地图地图地图

时间:2011-08-19 19:27:56

标签: c++ map iteration

我试图从矢量地图地图地图地图地图中收集所有数据,而不必在C ++中有7个循环。

以下是数据的外观:

Map 1=>Map 1.1=>Map 1.1.1=>Map 1.1.2=>Map 1.1.3=>Map 1.1.4=>Vector 1.1.5=>Elem 1
                                                                        =>Elem 2
       Map 1.2=>Map 1.2.1=>Map 1.2.2=>Map 1.2.3=>Map 1.2.4=>Vector 1.2.5=> Elem 1
                                                                        =>Elem 2
Map 2 =>Map 1.1=>Map 1.1.1=>Map 1.1.2=>Map 1.1.3=>Map 1.1.4=>Vector 1.1.5=>Elem 1
                                                                         =>Elem 2
        Map 1.2=>Map 1.2.1=>Map 1.2.2=>Map 1.2.3=>Map 1.2.4=>Vector 1.2.5=>Elem 1
                                                                         =>Elem 2

所以我试图将所有地图中的所有Elem 1,Elem 2收集到地图中。

有人可以帮我做这个而不是通过每个地图的明显循环并导致C ++中的7个循环吗?

感谢您的帮助。

3 个答案:

答案 0 :(得分:4)

我喜欢@ inflagranti的想法 - 所以,没有声称实用程序,这里是一个for-each模板,迭代所有东西。它使用pretty printer中的is_container特征,我在此不再复制。

更新:现在已经完全解决了裸值类型和配对值类型的问题。

更新2:简化了实施课程,感谢@Luc Danton。

#include <algorithm>

#include "prettyprint.hpp"    
using namespace pretty_print;  // for "is_container" trait

template <typename T> struct is_pair : public std::false_type { };
template <typename S, typename T> struct is_pair<std::pair<S,T>> : public std::true_type { };

template <typename T> struct final_value { typedef T type; };
template <typename S, typename T> struct final_value<std::pair<S,T>> { typedef T type; };

template <typename Iter, typename F> void for_each_recursive(Iter begin, Iter end, F f);

template <typename F, bool Recurse> struct for_each_rec_impl;

template <typename F>
struct for_each_rec_impl<F, false>
{
  template <typename Iter>
  static typename std::enable_if<is_pair<typename std::iterator_traits<Iter>::value_type>::value, void>::type
  go(Iter begin, Iter end, F f)
  {
    for (Iter it = begin; it != end; ++it) f(it->second);
  }

  template <typename Iter>
  static typename std::enable_if<!is_pair<typename std::iterator_traits<Iter>::value_type>::value, void>::type
  go(Iter begin, Iter end, F f)
  {
    for (Iter it = begin; it != end; ++it) f(*it);
  }
};

template <typename F>
struct for_each_rec_impl<F, true>
{
  template <typename Iter>
  static typename std::enable_if<is_pair<typename std::iterator_traits<Iter>::value_type>::value, void>::type
  go(Iter begin, Iter end, F f)
  {
    for (Iter it = begin; it != end; ++it)
      {
        for_each_recursive(it->second.begin(), it->second.end(), f);
      }
  }

  template <typename Iter>
  static typename std::enable_if<!is_pair<typename std::iterator_traits<Iter>::value_type>::value, void>::type
  go(Iter begin, Iter end, F f)
  {
    for (Iter it = begin; it != end; ++it)
      {
        for_each_recursive(it->begin(), it->end(), f);
      }
  }
};

template <typename Iter, typename F>
void for_each_recursive(Iter begin, Iter end, F f)
{
  typedef typename std::iterator_traits<Iter>::value_type value_type;
  typedef typename final_value<value_type>::type type;

  for_each_rec_impl<F, is_container<type>::value>::go(begin, end, f);
}

用法:for_each_recursive(v.begin(), v.end(), my_predicate<final_value_type>);

答案 1 :(得分:3)

除非更改数据类型,否则您可能会遇到循环内循环。

但是,我首先将......矢量地图的地图地图重新编写成1幅矢量地图。 我建议使用boost :: tuple或std :: tuple(C ++ 0x)创建类,但您也可以定义自己的类,并重载operator <以便它可以用作映射键(或写比较器)

使用boost :: tuple,如果你有map<Key1, map< Key2, map<Key3, map<Key4, map<Key5, map<Key6, vector<T> > > > > > >,你可以将其重新加工成map< boost::tuple< Key1, Key2, Key3, Key4, Key5, Key6 >, vector<T> >

答案 2 :(得分:2)

如果你真的必须,你可以做一些模板元编程(例如使用boost mpl)来抽象出循环。但是,正如许多人所建议的那样,原始问题的解决方案很可能比需要7个嵌套地图和矢量的解决方案更好。

相关问题