【问题标题】:How to make the equal_range iterator sorted by a different index in Boost Multi-index?如何在Boost Multi-index中使equal_range迭代器按不同的索引排序?
【发布时间】:2018-06-22 00:29:27
【问题描述】:

我在 employee 类上有一个 boost 多索引容器(取自 boost 官方文档):

typedef multi_index_container<
        employee,
        indexed_by<
                ordered_unique<
                        tag<id>,  BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
                ordered_non_unique<
                        tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>,
                ordered_non_unique<
                        tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >
> employee_set;

下面是容器中由(id, name, age)打印的数据示例:

0 Joe 31
1 Robert 27
2 John 40
3 Albert 20
4 John 57
5 John 58
6 John 22

我想要一个按年龄(最后一个字段)排序的名称为 John 的所有项目的迭代器。我尝试了equal_range 方法:

auto iter1 = boost::make_iterator_range(es.get<name>().equal_range("John"));

它返回一个迭代器,其中包含名称为 John 的所有记录。如何使这个迭代器按第三个索引(即年龄)排序?

输出应该是:

6 John 22
2 John 40
4 John 57
5 John 58

【问题讨论】:

  • 很遗憾您没有包含完整的工作代码。我现在自己做一个,但我可能没有时间回答这个问题
  • @sehe 对不起,下次我将代码添加到问题中。代码来自 boost 文档的第一个示例。 (boost.org/doc/libs/1_62_0/libs/multi_index/example/basic.cpp)
  • 是的,文档的链接将是一个好的开始。我知道文档包含不止一个示例 :)

标签: c++ boost boost-multi-index


【解决方案1】:

好的。这是复制者 Live On Coliru

输出确实是

2 "John" 40
4 "John" 57
5 "John" 58
6 "John" 22

现在要让它(注意单词的选择)按年龄排序,您可以使用复合键。所以而不是:

    bmi::ordered_non_unique<
        bmi::tag<struct name>,
        bmi::member<employee, std::string, &employee::name>
    >,

使用

    bmi::ordered_non_unique<
        bmi::tag<struct name_age>,
        bmi::composite_key<employee,
            bmi::member<employee, std::string, &employee::name>,
            bmi::member<employee, int, &employee::age>
        >
    >,

现在你可以

for (employee const& emp : boost::make_iterator_range(es.get<name_age>().equal_range("John"))) {
    std::cout << emp.id << " " << std::quoted(emp.name) << " " << emp.age << "\n";
}

打印

6 "John" 22
2 "John" 40
4 "John" 57
5 "John" 58

完整样本

Live On Coliru

#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/range/iterator_range.hpp>

namespace bmi = boost::multi_index;

struct employee {
    int id;
    std::string name;
    int age;
};

typedef bmi::multi_index_container<
    employee,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct id>,
            bmi::member<employee, int, &employee::id>
        >,
        bmi::ordered_non_unique<
            bmi::tag<struct name>,
            bmi::member<employee, std::string, &employee::name>
        >,
        bmi::ordered_non_unique<
            bmi::tag<struct name_age>,
            bmi::composite_key<employee,
                bmi::member<employee, std::string, &employee::name>,
                bmi::member<employee, int, &employee::age>
            >
        >,
        bmi::ordered_non_unique<
            bmi::tag<struct age>,
            bmi::member<employee, int, &employee::age>
        >
    > > employee_set;

#include <iostream>
#include <iomanip>

int main() {
    employee_set es {
        {0, "Joe",    31},
        {1, "Robert", 27},
        {2, "John",   40},
        {3, "Albert", 20},
        {4, "John",   57},
        {5, "John",   58},
        {6, "John",   22},
    };

    std::cout << "name index:\n";
    for (employee const& emp : boost::make_iterator_range(es.get<name>().equal_range("John"))) {
        std::cout << emp.id << " " << std::quoted(emp.name) << " " << emp.age << "\n";
    }

    std::cout << "name_age index:\n";
    for (employee const& emp : boost::make_iterator_range(es.get<name_age>().equal_range("John"))) {
        std::cout << emp.id << " " << std::quoted(emp.name) << " " << emp.age << "\n";
    }
}

打印

name index:
2 "John" 40
4 "John" 57
5 "John" 58
6 "John" 22
name_age index:
6 "John" 22
2 "John" 40
4 "John" 57
5 "John" 58

【讨论】:

  • 谢谢!复合键的概念非常强大。您可以使用 boost 多索引实现 SQL 数据库。
  • @motam79 是的。有一些限制(a.k.a.:没有灵丹妙药)。您不能期望获得神奇优化的索引,您将总是必须手动设计自己的“解释计划”。最重要的是,跨多个索引的查询将需要对一个索引进行 RANGE SCAN(sql 术语)。数据库在这里执行许多重要的优化和配置文件引导的选择。只要您非常了解您的数据(w.r.t. 索引密度),您就可以从 Boost MultiIndex 中获得很多好处。 (哦,还有不小的插入成本)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 2015-04-03
  • 2010-12-21
  • 1970-01-01
  • 2014-02-16
  • 2010-12-14
相关资源
最近更新 更多