gpt4 book ai didi

c++ - Boost 多索引容器与基于 std::unordered_map( map 的 map )的多级映射容器

转载 作者:可可西里 更新时间:2023-11-01 18:29:24 24 4
gpt4 key购买 nike

我最近发现了 boost::multi_index_container,我很好奇他的性能与我自己实现的基于多级映射的类似容器的比较,定义为:

typedef int      Data;
typedef uint64_t MainKey;
typedef uint64_t SecondaryKey;

typedef std::unordered_map<SecondaryKey, Data> SecondaryMap;
typedef std::unordered_map<PrimaryKey, SecondaryMap> PrimaryMap;

键的顺序并不重要。快速查找很重要,为此我使用了类似的东西:

// find primaryKey=10 and secondaryKey=30
PrimaryMap m;
....
auto i1 = m.find( 10);
if ( i1 != m.end())
{
auto& secondary = i1->second;
auto i2 = secondary.find( 30);
if ( i2 != secondary.end())
{
found = true;
....
}
}

我想知道会是什么

  • 最接近我的实现的 boost::multi_index_container 配置
  • 按主键和辅助键搜索的最快方法。

我已尝试配置模板,但我不确定这是否是最佳解决方案:

struct RecordKey
{
MainKey mainKey;
SecondaryKey secondaryKey;

RecordKey( const MainKey mainKey, SecondaryKey secondaryKey):
mainKey( mainKey),
secondaryKey( secondaryKey)
{}
};

struct Record: public RecordKey
{
Data data;

Record( const MainKey mainKey = 0, const SecondaryKey secondaryKey = 0, const Data& data = 0):
RecordKey( mainKey, secondaryKey),
data( data)
{}
};


struct MainKeyTag {};
struct SecondaryKeyTag {};
struct CompositeKeyTag {};

using boost::multi_index_container;
using namespace boost::multi_index;

typedef boost::multi_index_container<Record,
indexed_by < /*random_access<>,*/
hashed_non_unique<tag<MainKeyTag>, BOOST_MULTI_INDEX_MEMBER( RecordKey, MainKey, mainKey) >,
hashed_non_unique<tag<SecondaryKeyTag>, BOOST_MULTI_INDEX_MEMBER( RecordKey, SecondaryKey, secondaryKey) >,
hashed_unique<tag<CompositeKeyTag>, composite_key<Record, member<RecordKey, MainKey, &RecordKey::mainKey>,
member<RecordKey, SecondaryKey, &RecordKey::secondaryKey> > > > > RecordContainer;

最佳答案

通过在 BMI 中选择有序(而不是散列)索引,您可以吃蛋糕也可以吃。

ordered 复合索引有一个很好的属性,允许您通过部分键进行查询,因此您只需要定义复合索引就可以通过主索引进行查询:

typedef boost::multi_index_container<
Record,
indexed_by<
ordered_non_unique< tag<CompositeKeyTag>,
composite_key<Record,
member<RecordKey, MainKey, &RecordKey::mainKey>,
member<RecordKey, SecondaryKey, &RecordKey::secondaryKey>
> > > > RecordContainer;

现在你可以通过mainKey查询:

range = index.equal_range(10);

或复合:

range = index.equal_range(boost::make_tuple(10,30));

背景:

这是一个完整的演示 Live On Coliru :

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

using MainKey = uint64_t;
using SecondaryKey = uint64_t;
using Data = std::string;

struct RecordKey
{
MainKey mainKey;
SecondaryKey secondaryKey;

RecordKey( const MainKey mainKey, SecondaryKey secondaryKey):
mainKey( mainKey),
secondaryKey( secondaryKey)
{}
};

struct Record: public RecordKey
{
Data data;

Record( const MainKey mainKey = 0, const SecondaryKey secondaryKey = 0, const Data& data = 0):
RecordKey( mainKey, secondaryKey),
data( data)
{}

friend std::ostream& operator<<(std::ostream& os, Record const& r) {
return os << " Record[" << r.mainKey << ", " << r.secondaryKey << ", " << r.data << "]";
}
};

struct MainKeyTag {};
struct SecondaryKeyTag {};
struct CompositeKeyTag {};

using boost::multi_index_container;
using namespace boost::multi_index;

typedef boost::multi_index_container<
Record,
indexed_by<
ordered_non_unique< tag<CompositeKeyTag>,
composite_key<Record,
member<RecordKey, MainKey, &RecordKey::mainKey>,
member<RecordKey, SecondaryKey, &RecordKey::secondaryKey>
> > > > RecordContainer;


int main()
{
RecordContainer records;
records.insert(Record(10, 20, "12"));
records.insert(Record(10, 30, "13"));
records.insert(Record(10, 30, "13 - need not be unique!"));
records.insert(Record(30, 40, "34"));
records.insert(Record(30, 50, "35"));
records.insert(Record(50, 60, "56"));
records.insert(Record(50, 70, "57"));
records.insert(Record(70, 80, "78"));

std::cout << "\nAll records:\n----------------------------------------------------------------------\n";
for (auto const& r : records)
std::cout << r << "\n";

{
std::cout << "\nAll records with (main) == (10):\n----------------------------------------------------------------------\n";
auto& index = records.get<0>();
auto range = index.equal_range(10);
for (auto const& r : boost::make_iterator_range(range.first, range.second))
std::cout << r << "\n";
}

{
std::cout << "\nAll records with (main,secondary) == (10,30):\n----------------------------------------------------------------------\n";
auto& index = records.get<0>();
auto range = index.equal_range(boost::make_tuple(10,30));
for (auto const& r : boost::make_iterator_range(range.first, range.second))
std::cout << r << "\n";
}
}

输出:

All records:
----------------------------------------------------------------------
Record[10, 20, 12]
Record[10, 30, 13]
Record[10, 30, 13 - need not be unique!]
Record[30, 40, 34]
Record[30, 50, 35]
Record[50, 60, 56]
Record[50, 70, 57]
Record[70, 80, 78]

All records with (main) == (10):
----------------------------------------------------------------------
Record[10, 20, 12]
Record[10, 30, 13]
Record[10, 30, 13 - need not be unique!]

All records with (main,secondary) == (10,30):
----------------------------------------------------------------------
Record[10, 30, 13]
Record[10, 30, 13 - need not be unique!]

关于c++ - Boost 多索引容器与基于 std::unordered_map( map 的 map )的多级映射容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26467894/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com