C++ 通过自定义顺序迭代boost multi_索引
我有一个包含多个索引的boostC++ 通过自定义顺序迭代boost multi_索引,c++,boost,containers,boost-multi-index,C++,Boost,Containers,Boost Multi Index,我有一个包含多个索引的boostmulti_index容器。如何在迭代时使用指定的自定义比较来迭代元素 例如,假定Element::name和Element::index由multi_index容器索引 bool myCompare(const Element &lhs, const Element &rhs) { if(lhs.name == rhs.name) { return lhs.index < rhs.index; }
multi_index
容器。如何在迭代时使用指定的自定义比较来迭代元素
例如,假定Element::name
和Element::index
由multi_index
容器索引
bool myCompare(const Element &lhs, const Element &rhs)
{
if(lhs.name == rhs.name)
{
return lhs.index < rhs.index;
}
else
{
return lhs.name < rhs.name;
}
}
bool myCompare(常量元素和lhs、常量元素和rhs)
{
if(lhs.name==rhs.name)
{
返回lhs.index
但是,迭代不应限于上述情况,而是允许根据元素的索引成员进行任何类型的排序,类似于SQL SELECT排序。这不是多索引容器的功能 但是,您可以轻松创建额外的临时索引:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
奖金:使用重新排列
,您可以轻松地在多索引::随机访问
索引中保持排序:
table.get<external>().rearrange(temporary.begin());
演示
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
struct Element {
int index;
std::string name;
};
#include <tuple>
bool myCompare(const Element &lhs, const Element &rhs) {
return std::tie(lhs.name, lhs.index) < std::tie(rhs.name, rhs.index);
}
namespace bmi = boost::multi_index;
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct external> >
> >;
#include <iostream>
#include <vector> // for the temporary index
int main() {
Table table;
// generate 30 random records...
std::generate_n(back_inserter(table), 30,
[]{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; }
);
{
// temporary index:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
// iterate table in the order specified by myCompare:
std::sort(temporary.begin(), temporary.end(), myCompare);
for(Element const& e: temporary)
std::cout << e.index << "\t" << e.name << "\n";
// now to rearrange a random-access index on the multi-index container:
table.get<external>().rearrange(temporary.begin());
}
}
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct insertion_order> >,
// ready made index for traversal in composite order
bmi::ordered_non_unique<bmi::tag<struct readymade>,
bmi::composite_key<Element,
bmi::member<Element, std::string, &Element::name>,
bmi::member<Element, int, &Element::index>
>
>
> >;
int main() {
// generate 30 random records...
Table table;
std::generate_n(back_inserter(table), 30, []{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; });
// effectively "zero" cost iteration there:
for(Element const& e: table.get<readymade>())
std::cout << e.index << "\t" << e.name << "\n";
}
您可以看到,在名称相等的地方,较低的索引排在第一位
更新评论内容: 嗯?你是要魔法仙尘吗 你是要魔法仙尘吗?没有魔法 DBMS不使用任何异常的东西。它们通常使用BTrees,非常类似于花园中的数据结构 多样性
std::map
,或者实际上是bmi::ordered_u[non_u]唯一的
索引。因此,在这方面,Boost MultiIndex是(接近)您想要的,
已经
RDBMS es给表带来的主要附加功能是持久性。这样,一切都变得更有用、更具可扩展性和。。。较少的
效率高
所以,不要把DBMS看作效率的圣杯
内存中的键值数据存储被广泛用于提高性能是有原因的。另一个重要的注意事项是检索
SQL中的有序结果集的性能根本不好,除非索引已经存在
现在,如果您希望获得尽可能好的性能,您可能需要设计自己的数据结构(可能需要借助Boost)
但鉴于您提出这些问题的程度,我会在之前的一段较长时间内使用Boost Multi Index
是的。只需创建有时可能需要组合的索引,并编写一些“循环代码”,根据需要组合它们
思想
现在开箱思考,您可能想知道如何“轻松”实现两级排序,使DBMS
引擎可能会
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
struct Element {
int index;
std::string name;
};
#include <tuple>
bool myCompare(const Element &lhs, const Element &rhs) {
return std::tie(lhs.name, lhs.index) < std::tie(rhs.name, rhs.index);
}
namespace bmi = boost::multi_index;
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct external> >
> >;
#include <iostream>
#include <vector> // for the temporary index
int main() {
Table table;
// generate 30 random records...
std::generate_n(back_inserter(table), 30,
[]{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; }
);
{
// temporary index:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
// iterate table in the order specified by myCompare:
std::sort(temporary.begin(), temporary.end(), myCompare);
for(Element const& e: temporary)
std::cout << e.index << "\t" << e.name << "\n";
// now to rearrange a random-access index on the multi-index container:
table.get<external>().rearrange(temporary.begin());
}
}
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct insertion_order> >,
// ready made index for traversal in composite order
bmi::ordered_non_unique<bmi::tag<struct readymade>,
bmi::composite_key<Element,
bmi::member<Element, std::string, &Element::name>,
bmi::member<Element, int, &Element::index>
>
>
> >;
int main() {
// generate 30 random records...
Table table;
std::generate_n(back_inserter(table), 30, []{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; });
// effectively "zero" cost iteration there:
for(Element const& e: table.get<readymade>())
std::cout << e.index << "\t" << e.name << "\n";
}
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct insertion_order> >,
// separate indices that we might combine in some way later::
bmi::ordered_non_unique<bmi::tag<struct by_index>, bmi::member<Element, int, &Element::index> >,
bmi::ordered_non_unique<bmi::tag<struct by_name>, bmi::member<Element, std::string, &Element::name> >
> >;
使用Table=boost::multi_index_container>;
现在,组合索引成为“引擎”的工作,或者,在本例中是您的算法。这里有一个想法:
template <typename Index1, typename Index2, typename Table, typename Function>
void SelectOrderBy2(Table const& table, Function function) {
using T = typename Table::value_type const;
auto& idx1 = table.template get<Index1>();
auto& idx2 = table.template get<Index2>();
auto it = idx1.begin(), end = idx1.end();
while (it!=end) {
auto next = idx1.upper_bound(idx1.key_extractor()(*it));
std::set<boost::reference_wrapper<T>, typename Table::template index<Index2>::type::value_compare>
set(idx2.value_comp());
while (it != next)
set.insert(set.end(), boost::cref(*it++));
for (auto& e: set)
function(e);
}
}
模板
void SelectOrderBy2(表常量和表、函数){
使用T=typename表::value\u type const;
auto&idx1=table.template get();
auto&idx2=table.template get();
auto it=idx1.begin(),end=idx1.end();
while(it!=结束){
auto-next=idx1.upper_-bound(idx1.key_提取器()(*it));
std::set
set(idx2.value_comp());
while(it!=下一个)
set.insert(set.end(),boost::cref(*it++);
用于(自动和电气:设置)
职能(e);
}
}
这是一些非常容易出错的模板代码,但您可以非常简单地使用它:
SelectOrderBy2<by_name, by_index>(
table,
[](Element const& e) { std::cout << e.index << "\t" << e.name << "\n"; }
);
选择OrderBy2(
桌子
[](Element const&e){std::cout这不是多索引容器的特性
但是,您可以轻松创建额外的临时索引:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
奖金:使用重新排列
,您可以轻松地在多索引::随机访问
索引中保持排序:
table.get<external>().rearrange(temporary.begin());
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
struct Element {
int index;
std::string name;
};
#include <tuple>
bool myCompare(const Element &lhs, const Element &rhs) {
return std::tie(lhs.name, lhs.index) < std::tie(rhs.name, rhs.index);
}
namespace bmi = boost::multi_index;
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct external> >
> >;
#include <iostream>
#include <vector> // for the temporary index
int main() {
Table table;
// generate 30 random records...
std::generate_n(back_inserter(table), 30,
[]{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; }
);
{
// temporary index:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
// iterate table in the order specified by myCompare:
std::sort(temporary.begin(), temporary.end(), myCompare);
for(Element const& e: temporary)
std::cout << e.index << "\t" << e.name << "\n";
// now to rearrange a random-access index on the multi-index container:
table.get<external>().rearrange(temporary.begin());
}
}
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct insertion_order> >,
// ready made index for traversal in composite order
bmi::ordered_non_unique<bmi::tag<struct readymade>,
bmi::composite_key<Element,
bmi::member<Element, std::string, &Element::name>,
bmi::member<Element, int, &Element::index>
>
>
> >;
int main() {
// generate 30 random records...
Table table;
std::generate_n(back_inserter(table), 30, []{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; });
// effectively "zero" cost iteration there:
for(Element const& e: table.get<readymade>())
std::cout << e.index << "\t" << e.name << "\n";
}
您可以看到,在名称相等的地方,较低的索引排在第一位
更新评论内容: 嗯?你是要魔法仙尘吗 你是要魔法仙尘吗?没有魔法 数据库管理系统不会使用任何不寻常的东西。它们通常使用BTrees,非常类似于花园中的数据结构 多样性
std::map
,或者实际上是bmi::ordered_uu[non_u]unique
索引。因此,在这方面,Boost MultiIndex是(接近)您想要的,
已经
RDBMS es给表带来的主要附加功能是持久性。有了持久性,一切都变得更有用、更具可扩展性和…更少
效率高
所以,不要把DBMS看作效率的圣杯
内存中的键值数据存储被广泛用于性能方面是有原因的
SQL中的有序结果集的性能根本不好,除非索引已经存在
现在,如果您希望获得尽可能好的性能,您可能需要设计自己的数据结构(可能需要借助Boost)
但鉴于您提出这些问题的程度,我会在之前的一段较长时间内使用Boost Multi Index
可以。只需创建有时需要合并的索引,并编写一些“循环代码”,根据需要合并它们
思想
现在开箱思考,您可能想知道如何“轻松”实现两级排序,使DBMS
引擎可能会
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
struct Element {
int index;
std::string name;
};
#include <tuple>
bool myCompare(const Element &lhs, const Element &rhs) {
return std::tie(lhs.name, lhs.index) < std::tie(rhs.name, rhs.index);
}
namespace bmi = boost::multi_index;
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct external> >
> >;
#include <iostream>
#include <vector> // for the temporary index
int main() {
Table table;
// generate 30 random records...
std::generate_n(back_inserter(table), 30,
[]{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; }
);
{
// temporary index:
std::vector<boost::reference_wrapper<Element const> > temporary(table.begin(), table.end());
// iterate table in the order specified by myCompare:
std::sort(temporary.begin(), temporary.end(), myCompare);
for(Element const& e: temporary)
std::cout << e.index << "\t" << e.name << "\n";
// now to rearrange a random-access index on the multi-index container:
table.get<external>().rearrange(temporary.begin());
}
}
using Table = boost::multi_index_container<Element,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct insertion_order> >,
// ready made index for traversal in composite order
bmi::ordered_non_unique<bmi::tag<struct readymade>,
bmi::composite_key<Element,
bmi::member<Element, std::string, &Element::name>,
bmi::member<Element, int, &Element::index>
>
>
> >;
int main() {
// generate 30 random records...
Table table;
std::generate_n(back_inserter(table), 30, []{ return Element { rand()%100, std::string(1, 'a'+rand()%26) }; });
// effectively "zero" cost iteration there:
for(Element const& e: table.get<readymade>())
std::cout << e.index << "\t" << e.name << "\n";
}