[英]How to iterate through map of map of map of map of map of map of vector
我試圖在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個循環嗎?
謝謝您的幫助。
我喜歡@inflagranti的想法-因此,在不要求實用程序的情況下,這是一個遍歷所有內容的for-each模板。 它使用了漂亮打印機的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>);
除非更改數據類型,否則您可能會陷入循環內循環的困境。
但是,我將從將.. vector的地圖的地圖重寫為1個vector的地圖開始。 我建議使用boost :: tuple或std :: tuple(C ++ 0x)創建類,但是您也可以定義自己的類,並重載運operator <
以便將其用作映射鍵(或編寫比較器)
使用boost :: tuple,如果您有map<Key1, map< Key2, map<Key3, map<Key4, map<Key5, map<Key6, vector<T> > > > > > >
可以將其重新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> >
。
如果確實需要,則可以執行一些模板元編程(例如,使用boost mpl),以抽象出循環。 但是,正如許多人所建議的那樣,比起需要7個嵌套映射和一個矢量的解決方案,有一種更好的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.