2011-11-03 18 views
6

私は2つの整数キーK1とK2に従ってオブジェクトを格納するためにBoost multi_indexコンテナを使用しています。たとえば、最初のインデックスを取得し、find()関数(K2と値Yのidem)を使用することで、 "K1 == X"を満たすすべての要素のイテレータを簡単に取得できますが、 K1 == XとK2 == Yの両方を満たすすべての要素のイテレータを取得することができます。明らかな解決策は、K1 == Xを満たすすべての要素に対してイテレータを取得し、述語K2 == Yを持つboost :: filter_iteratorを構築し、 Boost.MultiIndexからのみ(多分より効率的に)行う方法がありますか?Boost.MultiIndex:複数のフィールドを使って要素を検索する

おかげ

マチュー

+0

は 'X'と 'Y'に基づいてソートされた連想インデックスを作成しますか?それはすでにあなたがやっていることのように聞こえる。あなたはコンテナ宣言を投稿したいかもしれません。 –

答えて

6

あなたがK1K2の両方でboost::multi_index::composite_keyを使用することができます。ここで

ideone.comにもある小さな例、:

#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/composite_key.hpp> 

#include <iostream> 

struct Stuff 
{ 
    Stuff (int iFirst, int iSecond) 
     : m_iFirst(iFirst), 
      m_iSecond(iSecond) 
    { 
    } 

    int m_iFirst; 
    int m_iSecond; 

}; 

std::ostream& operator<<(std::ostream& rOut, Stuff const& rStuff) 
{ 
    return rOut << rStuff.m_iFirst << "/" << rStuff.m_iSecond << "\n"; 
} 


struct FirstIdx{}; 
struct SecondIdx{}; 
struct BothIdx{}; 

typedef boost::multi_index_container< 
    Stuff, 
    boost::multi_index::indexed_by< 
     boost::multi_index::ordered_non_unique<boost::multi_index::tag<FirstIdx>, boost::multi_index::member<Stuff, int, &Stuff::m_iFirst> >, 
     boost::multi_index::ordered_non_unique<boost::multi_index::tag<SecondIdx>, boost::multi_index::member<Stuff, int, &Stuff::m_iSecond> >, 
     boost::multi_index::ordered_non_unique<boost::multi_index::tag<BothIdx>, boost::multi_index::composite_key<Stuff, boost::multi_index::member<Stuff, int, &Stuff::m_iFirst>, 
                                  boost::multi_index::member<Stuff, int, &Stuff::m_iSecond> > > 
     > 
    > TDicStuffs; 

typedef TDicStuffs::index<FirstIdx>::type TFirstIdx; 
typedef TDicStuffs::index<SecondIdx>::type TSecondIdx; 
typedef TDicStuffs::index<BothIdx>::type TBothIdx; 

int main(int argc, char *argv[]) 
{ 

    TDicStuffs stuffs; 

    // fill some stuffs 
    stuffs.insert(Stuff(1, 1)); 
    stuffs.insert(Stuff(1, 2)); 
    stuffs.insert(Stuff(1, 3)); 
    stuffs.insert(Stuff(2, 1)); 
    stuffs.insert(Stuff(2, 2)); 
    stuffs.insert(Stuff(2, 3)); 
    stuffs.insert(Stuff(3, 1)); 
    stuffs.insert(Stuff(3, 2)); 
    stuffs.insert(Stuff(3, 3)); 

    assert(stuffs.size() == 9); 

    // search for m_iFirst == 2 
    TFirstIdx::const_iterator itFirstLower; 
    TFirstIdx::const_iterator itFirstUpper; 

    boost::tie(itFirstLower, itFirstUpper) = stuffs.get<FirstIdx>().equal_range(2); 

    assert(std::distance(itFirstLower, itFirstUpper) == 3); 

    std::copy(itFirstLower, itFirstUpper, std::ostream_iterator<Stuff>(std::cout << "\n")); 

    // search for m_iSecond == 3 
    TSecondIdx::const_iterator itSecondLower; 
    TSecondIdx::const_iterator itSecondUpper; 

    boost::tie(itSecondLower, itSecondUpper) = stuffs.get<SecondIdx>().equal_range(3); 

    assert(std::distance(itSecondLower, itSecondUpper) == 3); 

    std::copy(itSecondLower, itSecondUpper, std::ostream_iterator<Stuff>(std::cout << "\n")); 

    // search for m_iFirst == 2 m_iSecond == 3 
    TBothIdx::const_iterator itBothLower; 
    TBothIdx::const_iterator itBothUpper; 

    boost::tie(itBothLower, itBothUpper) = stuffs.get<BothIdx>().equal_range(boost::make_tuple(2,3)); 

    assert(std::distance(itBothLower, itBothUpper) == 1); 

    std::copy(itBothLower, itBothUpper, std::ostream_iterator<Stuff>(std::cout << "\n")); 

    return 0; 
} 
+1

実際には、3つのインデックスを持つ必要はありません。最初のものにコンポジットキーエクストラクタを装備し、m_iFirstとon(m_iFirst、m_iSecond)の両方に基づいたルックアップに使用することができます。 –

+2

@JoaquínMLópezMuñoz:そうだけど、デモンストレーションのためだけに追加しました。 – Lars

+0

ありがとう、私は複合キーのソリューションが好きです。 – sunmat

関連する問題