2011-08-19 89 views
0

我試圖從一張地圖映射的地圖映射地圖的所有數據而不必有7個地圖映射地圖在C++中循環。如何通過向量地圖映射地圖映射

下面是數據的外觀:

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,2 ELEM。

有人可以幫我做到這一點,而不是通過每個地圖的明顯循環,並導致在C++ 7循環?

感謝您的幫助。

+30

不......... –

+7

爲什麼你有這樣的深度嵌套的地圖和引導?與其試圖迭代你的map-of-a-map -... of-a-vector,可能有更好的方法來構造你的代碼,使它變得沒有必要。 – Alex

+6

你很清楚地意識到,這已經有點遠了,因爲你不願意編寫七個嵌套for循環,但是如果你有七個嵌套的地圖,你還能做什麼?這有點荒謬,必須有另一種選擇。如果你解釋你想達到的目標,有人會建議更好的方法。 – john

回答

3

我喜歡@ inflagranti的想法 - 所以,沒有聲稱實用,這裏是一個for-each模板,遍歷所有內容。它使用來自pretty printeris_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>);

2

如果你真的必須,你可以做一些模板元編程(例如使用boost mpl)來抽象出循環。然而,正如很多人所建議的那樣,對於原始問題,很可能有比需要7個嵌套地圖和向量的更好的解決方案。

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> >

+0

C++ 0x現在是C++ 11 – Xirdus

+0

@ Xirdus:它可能會在標準發佈後發佈。我仍然屏住呼吸。 –