How to iterate through map of map of map of map of map of map of vector
I am trying to gather all the data from a map of map of map of map of map of map of map of vector without having to have 7 loops in C++.
Here is how the data looks:
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
So I am trying to collect all the Elem 1, Elem 2 from all the maps into a map.
开发者_如何学编程Can someone help me do this instead of the obvious loop through each map and leading to 7 loops in C++?
Thanks for the help.
(Update: Wow looking back at this after 10 years, what a code nightmare it was trying to fix someone else's legacy code. Hopefully no needs this now :)
I like @inflagranti's idea - so, without claim to utility, here's a for-each template that iterates over everything. It uses the is_container
trait from the pretty printer, which I don't replicate here.
Update: Now fully worked out to deal with both with naked value types and with pair value types.
Update 2: Simplified the implementation class, thanks to @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);
}
Usage: for_each_recursive(v.begin(), v.end(), my_predicate<final_value_type>);
Barring a change of the data type, you're probably stuck with loops-within-loop.
However, I would start by re-writing the maps of maps of maps of .... vector into 1 map of vectors.
I would recommend using either boost::tuple or std::tuple (C++0x) to create the class, but you can also define your own, and overload operator <
so that it can be used as a map key (or write the comparator)
Using boost::tuple, if you have map<Key1, map< Key2, map<Key3, map<Key4, map<Key5, map<Key6, vector<T> > > > > > >
you could rework it into map< boost::tuple< Key1, Key2, Key3, Key4, Key5, Key6 >, vector<T> >
.
If you really must, you could do some template meta programming (for instance using boost mpl), to abstract away the loops. However, as many people have suggested, there is very likely a better solution to your original problem than one that needs 7 nested maps and a vector.
精彩评论