2011-11-03 34 views
6

Tôi đang sử dụng vùng chứa Multi_index Boost để lưu trữ các đối tượng theo 2 khóa nguyên K1 và K2. Tôi có thể dễ dàng truy xuất một trình lặp trên tất cả các phần tử thỏa mãn "K1 == X", bằng cách lấy chỉ mục đầu tiên và sử dụng hàm find() (idem cho K2 và giá trị Y), nhưng tôi đang tìm cách để có được một iterator trên tất cả các yếu tố đáp ứng cả K1 == X và K2 == Y. Một giải pháp rõ ràng là để có được một iterator trên tất cả các yếu tố đáp ứng K1 == X sau đó xây dựng một tăng :: filter_iterator với vị ngữ K2 == Y, nhưng có cách nào để làm điều đó (có thể hiệu quả hơn) chỉ từ Boost.MultiIndex?Boost.MultiIndex: tìm kiếm các phần tử sử dụng nhiều trường

Cảm ơn

Matthieu

+0

Tạo một chỉ số kết hợp được sắp xếp dựa trên 'x' và 'y'? Điều đó nghe có vẻ giống như những gì bạn đang làm. Bạn có thể muốn đăng tuyên bố vùng chứa của mình. –

Trả lời

6

Bạn có thể sử dụng một boost::multi_index::composite_key với cả K1K2.

Dưới đây là một ví dụ nhỏ, mà cũng là trên 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

Trong thực tế, không cần phải có ba chỉ số: bạn chỉ có thể trang bị cho người đầu tiên một bộ tách khóa tổng hợp và sử dụng nó để tra cứu dựa trên cả m_iFirst và on (m_iFirst, m_iSecond). –

+2

@ Joaquín M López Muñoz: bạn nói đúng, nhưng tôi đã thêm chúng chỉ để trình diễn. – Lars

+0

Cảm ơn rất nhiều, tôi thích giải pháp với phím tổng hợp. – sunmat

Các vấn đề liên quan