【问题标题】:Boost Multi Index: index based on list contentBoost Multi Index:基于列表内容的索引
【发布时间】:2015-09-30 14:09:03
【问题描述】:

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

struct A {
   int id;
}

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

每个 A 都有一个严格唯一的 ID,我希望能够使用单个多索引容器,能够查找 B。 通过 B 的 ID 和 A 的 ID。

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

编辑:

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

我有卫星,它们又具有许多转发器和许多源。 我希望能够为给定的 Transponder id 或 Source 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 提供的示例中,我看到如果我要生成一个关系结构会更容易一些。我想我会试一试... :)

【问题讨论】:

  • 你应该使样本真实。如前所述,多图或双图就足够了。 “但是,我有其他参数来进行这种查找”(什么?)。请明确点。另外,尽量不要损坏类型名称,因为这样会导致无法发现潜在的 XY 问题

标签: c++ boost


【解决方案1】:

在没有确切用例的情况下,这里有一些建议,可以根据您展示的内容对索引进行建模¹

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_* 索引中是通用的:

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>
            >
        >
    >
>;

这是一个小演示:

Live On Coliru

#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";
}

打印:

Product 4 is in category 6
Product 5 is in category 6
Product 6 is in category 6

¹我将类名水晶球化成“现实”的东西

【讨论】:

  • 编辑了我的问题,感谢您提供此示例,我会试一试,但正如我在编辑中所说,我不允许编辑原始结构。这使得实施该策略变得更加复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 2011-07-28
  • 2010-12-21
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多