Boost.MultiIndex:使用多个字段搜索元素

发布于 2024-12-13 16:16:17 字数 304 浏览 3 评论 0原文

我使用 Boost multi_index 容器根据 2 个整数键 K1 和 K2 存储对象。我可以轻松地检索满足“K1 == X”的所有元素的迭代器,例如,通过获取第一个索引并使用 find() 函数(同上 K2 和值 Y),但我正在寻找一种方法获取满足 K1 == X 和 K2 == Y 的所有元素的迭代器。一个明显的解决方案是获取满足 K1 == X 的所有元素的迭代器,然后使用谓词 K2 == Y 构建 boost::filter_iterator,但有吗一种只能从 Boost.MultiIndex 做到这一点的方法(也许更有效)?

谢谢马蒂厄

I'm using a Boost multi_index container to store objects according to 2 integer keys K1 and K2. I can easily retrieve an iterator over all elements satisfying "K1 == X", for instance, by taking the first index and using the find() function (idem for K2 and a value Y), but I'm looking for a way to get an iterator over all elements satisfying both K1 == X and K2 == Y. An obvious solution is to get an iterator over all elements satisfying K1 == X then build a boost::filter_iterator with the predicate K2 == Y, but is there a way to do that (maybe more efficiently) only from Boost.MultiIndex?

Thanks

Matthieu

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏至、离别 2024-12-20 16:16:17

您可以使用 boost::multi_index::composite_key 同时具有 K1K2

这是一个小例子,也在 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;
}

You can use a boost::multi_index::composite_key with both K1and K2.

Here a small example, which is also on 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文