2011-11-03 8 views
6

Utilizzo un contenitore Boost multi_index per memorizzare gli oggetti in base a 2 chiavi integer K1 e K2. Posso facilmente recuperare un iteratore su tutti gli elementi che soddisfano "K1 == X", ad esempio, prendendo il primo indice e usando la funzione find() (idem per K2 e un valore Y), ma sto cercando un modo per ottenere un iteratore su tutti gli elementi che soddisfano sia K1 == X che K2 == Y. Una soluzione ovvia è ottenere un iteratore su tutti gli elementi che soddisfano K1 == X quindi creare un boost :: filter_iterator con il predicato K2 == Y, ma c'è un modo per farlo (forse in modo più efficiente) solo da Boost.MultiIndex?Boost.MultiIndex: ricerca di elementi utilizzando più campi

Grazie

Matthieu

+0

creare un indice associativo ordinato sulla base di 'X' e' y'? Questo suona come quello che stai facendo già però. Si potrebbe desiderare di pubblicare la dichiarazione del contenitore. –

risposta

6

è possibile utilizzare un boost::multi_index::composite_key sia con K1 e K2.

Ecco un piccolo esempio, che è anche sulla 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

Infatti, non è necessario avere tre indici: si può semplicemente equipaggiare il primo con un estrattore di chiavi composite e usarlo per ricerche basate sia su m_iFirst che su (m_iFirst, m_iSecond). –

+2

@ Joaquín M López Muñoz: hai ragione, ma li ho aggiunti solo per dimostrazione. – Lars

+0

Grazie mille, mi piace la soluzione con la chiave composita. – sunmat

Problemi correlati