C++ 多索引映射
Posted
技术标签:
【中文标题】C++ 多索引映射【英文标题】:C++ a multiple indexes map 【发布时间】:2021-07-12 01:47:23 【问题描述】:我正在实现一个简单的搜索系统,其中所有数据都存储在正在运行的进程的内存中。
最初,我打算使用元组的映射来实现这一点。
map<tuple<int, string, ...>, string> dict
但是,它只有在所有密钥都已知且不丢失时才有效。
例如,比如说,我有, map, value> 字典;
如果没有 key2 或 key2 是“无关”,我无法搜索地图
C++ 中是否有任何标准库或函数可以做到这一点?
非常感谢任何帮助。
【问题讨论】:
不,C++ 库中没有这样的东西。由于许多基本原因,在技术上不可能做任何事情,无论是使用地图还是 C++ 库中的任何其他关联容器。您将必须设计和实现自己的容器,该容器为每个键使用单独的映射/无序映射。 诚实的问题,但是您是否考虑过使用关系数据库?这将使进行任意查询变得更加容易,并且它们旨在为您处理索引和存储。 不,由于要求,它不打算使用数据库。 【参考方案1】:std::map<int, std::map<string, std::map< ... , string > ... > > dict;
您可以在任何步骤“不在乎”。您必须检查那里的每一个可能性。
你可以做一个组合爆炸来做所有 n!排序,并让所有内容都指向一个共享指针或类似的东西。
这并不便宜。
在每种可能性(n!)中排列参数,然后从每个增强选项(具有最小和最大状态)的元组映射到相同的共享数据 ptr。您现在可以执行将左侧或右侧视为最不重要的排序,并使用equal_range
不关心该键。
您可以改为使用四叉树或八叉树或 n 树结构之类的东西进行攻击。这会进行多维“排序”。让它与任意键一起工作会很有趣。
【讨论】:
而不是在每种可能性中排列参数,也许可以考虑使用类似 map这是我几年前碰巧研究过的一个有趣且重要的问题:
问题在于,在给定 n 个键的情况下,能够有效地查询这些键的任意子集。 在数据库术语中,这可以通过创建 m 索引来解决,这样每个键组合都被某个索引覆盖。问题描述here:索引数为C(n,floor(n/2)),其中 C(a,b) 是二项式系数a choose b。对于 n=5,所需索引的数量为 m=10。 我设计了an algorithm 来确定实际索引是什么。在 n=5 且键为 a、b、c、d的情况下>, e, 你可以使用索引(acedb),(baedc),(bdaec),(bedca),(cbaed),(cdbae),(cebad),(daceb), (decab),(eadbc)。这里的一个关键方面是索引可以用于较短的键组合。例如,(acedb) 涵盖以下内容(按字母顺序重新排列):(a),(ac),(ace),(acde),(abcde)。这就是为什么您可以仅使用 10 个索引而不是 25-1=31 来覆盖任意组合的原因。 现在,Boost.MultiIndex 可用于实际指定和使用这些索引。 example 有 4 个键,如果您愿意,可以轻松扩展到 5 个键。【讨论】:
【参考方案3】:你问:
C++ 中是否有任何标准库或函数可以做到这一点?
这个问题的答案是否。
要求有点模糊,因为您似乎有一个特定的界面。你应该定义你的接口,以及你期望它们做什么。
find()
like 函数的实现可以用多索引数据结构来实现。大致:
set
)。
对于每个关键字段,创建一个map
,将该关键字段中的值与set
记录中的迭代器set
相关联。
find
方法将遍历键 map
s 的集合,并计算返回的迭代器 set
s 的交集。
【讨论】:
这似乎与我在上一个解决方案中刚刚回答的想法相似。也就是为每个关键字段创建一个映射【参考方案4】:不在std
中,但有boost::multi_index
,它允许您将数据的任意投影指定为键,并且您可以拥有任意数量的键。
// your keys and value
struct Datum
key1_t key1;
key2_t key2;
key3_t key3;
// etc ...
value_t value;
;
namespace bmi = boost::multi_index;
// some unique types
struct Key1 ;
struct Key2 ;
struct Key3 ;
struct Key1Key2 ;
struct Key1Key2Key3 ;
using Dict = boost::multi_index_container<Datum, bmi::indexed_by<
bmi::ordered_unique<bmi::tag<Key1>, bmi::key<&Datum::key1>>, // just key 1
bmi::ordered_unique<bmi::tag<Key2>, bmi::key<&Datum::key2>>, // just key 2
bmi::ordered_unique<bmi::tag<Key3>, bmi::key<&Datum::key3>>, // just key 3
bmi::ordered_unique<bmi::tag<Key1Key2>, bmi::key<&Datum::key1, &Datum::key2>>, // key 1 then key 2
bmi::ordered_unique<bmi::tag<Key1Key2Key3>, bmi::key<&Datum::key1, &Datum::key2, &Datum::key3>>, // key 1 then key 2 then key 3
>;
int main()
Dict dict = /* stuff */
key1_t key1 = /* stuff */
key2_t key2 = /* stuff */
key3_t key3 = /* stuff */
auto it1 = dict.get<0>().find(key1); // select which by position
auto it2 = dict.get<Key2>().find(key2); // or by the tag types
auto it5 = dict.get<Key1Key2Key3>().find( key1, key2, key3 ); // multiple keys
【讨论】:
看起来不错,但是从您的代码看来,我需要指定所有的键组合?我的意思是,如果我有 10 个(甚至更多)键,那就太多了。以上是关于C++ 多索引映射的主要内容,如果未能解决你的问题,请参考以下文章