Boost Multi Index:基于列表内容的索引

时间:2015-09-30 14:09:03

标签: c++ boost

我是Boost Multi Index容器的新手,并且想知道它是否能以更有效的方式解决我的问题,因此简化了:

struct A {
   int id;
}

struct B {
   int id;
   std::list<A> products;
}

每个A都有一个严格唯一的ID,我想能够用一个多索引容器,能够找到B. 由B的身份和A的身份证明。

目前我正在使用好的std :: map,并将A ID链接到B ID。 所以说。它工作得很好。但是,我有其他参数来进行这样的查找并且它变得非常讨厌:)

编辑:

根据评论请求,我会详细说明:

我是卫星,而卫星则拥有许多转发器和许多来源。 我希望能够为给定的转发器ID或源ID(确实是唯一的)找到一个Satellite

可悲的是,我没有掌握卫星结构,意味着,我无法改变它。

简单地看起来像是:

struct Satellite {
 int norad_id;
 std::list<Transponder> transponders;
 std::list<Source> sources;
 ... some more data
}

我想要做的只是搜索任何一个卫星,找到一个具有特定转发器,或源,或者norad id的卫星。

目前,我正在使用3张不错的地图

std::map<int /*norad*/ ,Satellite> satellites;
std::map<int /*transponder  id*/, int/* norad */> transponder_to_satellite;
std::map<int /* source_id */,  int /* norad */ > source_to_satellite;

从@sehe提供的示例中,我发现如果我要生成关系结构会更容易一些。我想我会尝试一下...... :)

1 个答案:

答案 0 :(得分:1)

由于缺乏确切的用例,这里有一些根据你所展示的内容对指数进行建模的建议¹

   @Override
   public void beforeTextChanged(CharSequence s, int start, int count,
     int after) {
    // TODO Auto-generated method stub
    String str = YourEditText.getText().toString();
    len = str.length();
   }

你也可以使用复合键变得非常聪明,它在struct Product { int id; }; struct Category { int id; }; struct ProductCategoryRelation { int productId; int categoryId; }; namespace bmi = boost::multi_index; using RelationTable = bmi::multi_index_container< ProductCategoryRelation, bmi::indexed_by< bmi::ordered_unique< bmi::tag<struct by_product>, bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId> >, bmi::ordered_unique< bmi::tag<struct by_category>, bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId> > > >; 索引中是通用的:

ordered_*

这是一个小型演示:

<强> Live On Coliru

using RelationTable = bmi::multi_index_container<
    ProductCategoryRelation,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct by_product>,
            bmi::composite_key<ProductCategoryRelation,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId>,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId>
            >
        >
    >
>;

打印:

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <list>

struct Product {
   int id;
};

struct Category {
   int id;
};

struct ProductCategoryRelation {
    int productId;
    int categoryId;
};

namespace bmi = boost::multi_index;

using RelationTable = bmi::multi_index_container<
    ProductCategoryRelation,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct compound>,
            bmi::composite_key<ProductCategoryRelation,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId>,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId>
            >
        >
    >
>;

#include <iostream>
#include <boost/range/iterator_range.hpp>

int main() {
    RelationTable table {
        ProductCategoryRelation { 1, 7 },
        ProductCategoryRelation { 2, 7 },
        ProductCategoryRelation { 3, 7 },
        ProductCategoryRelation { 4, 6 },
        ProductCategoryRelation { 5, 6 },
        ProductCategoryRelation { 6, 6 },
        ProductCategoryRelation { 7, 5 },
        ProductCategoryRelation { 8, 5 },
        ProductCategoryRelation { 9, 5 },
    };

    // find all products in category 6:
    for (auto& rel : boost::make_iterator_range(table.get<compound>().equal_range(6)))
        std::cout << "Product " << rel.productId << " is in category " << rel.categoryId << "\n";
}

¹我把班级名称变成了“真实的”