2011-11-03 98 views
6

我使用Boost multi_index容器根據2個整數鍵K1和K2存儲對象。例如,我可以輕鬆地檢索遍歷滿足「K1 == X」的所有元素的迭代器,例如,通過獲取第一個索引並使用find()函數(同義詞K2和值Y),但我正在尋找一種方法獲得滿足K1 == X和K2 == Y的所有元素的迭代器。一個明顯的解決方案是獲取滿足K1 == X的所有元素的迭代器,然後用謂詞K2 == Y構建boost :: filter_iterator,但有沒有一種方法可以做到這一點(也許更有效),只能從Boost.MultiIndex?Boost.MultiIndex:使用多個字段搜索元素

感謝

馬修

+0

創建基於'X'和'Y'排序的關聯索引?這聽起來像你正在做的事情。您可能想要發佈您的容器聲明。 –

回答

6

您可以使用boost::multi_index::composite_keyK1K2

這裏一個小例子,這也是對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

實際上,不需要有三個索引:您可以只爲第一個索引裝備一個組合鍵提取器,並將其用於基於m_iFirst和on(m_iFirst,m_iSecond)的查找。 –

+2

@JoaquínMLópezMuñoz:你說得對,但我只是爲了演示而添加了它們。 – Lars

+0

非常感謝,我喜歡使用複合鍵的解決方案。 – sunmat