我查看了类似这样的问题,但似乎大多数答案都建议使用类似sqlite的内存数据库。也许这是唯一真正的解决方案,但无论如何我都会问。
我有许多记录如下:
struct record
{
int id;
int type;
// bunch of other data
}
问题涉及将一些这些存储在一个数据结构中,以便进行有效的运行时查询,如
GetAllForId(int)
GetAllOfType(int)
GetAllOfTypeAndId(int,int)
给定'id'可能有多个'type'记录 对于不同的'id',可以有多个'type'记录
我还希望能够轻松修改任何
结果中的值GetAllOfTypeAndId(int,int)
当然,以(优选地)低成本进行插入和删除。虽然插入很少,所以我可以在这里吃一点费用。
作为参考,我尝试了以下解决方案:
multimap<type,record>
然后迭代所有记录以找到相关类型之一。感觉非常麻烦,尤其是在执行GetAllOfTypeAndId查询时,对GetAllOfId查询有用
map<id,map<type,record>>
允许良好的GetAllOfTypeAndId查询,但无法提供对GetAllofType的正确访问
不幸的是,由于这个项目的性质,我可能无法使用关系数据库系统,即使它在内存中。
答案 0 :(得分:2)
听起来你想要MultiIndex。 Joaquin M Lopez提供了一个出色的数据结构,它允许跨多个字段,成员函数或结构/类的其他属性的索引。
在您的情况下,我们可以执行以下操作:
struct record
{
int id;
int type;
// bunch of other data
};
struct id_tag {};
struct type_tag {};
using record_container = boost::multi_index_container<
record,
boost::indexed_by<
boost::hashed_unique<
boost::multi_index::tag<id_tag>,
boost::multi_index::member<record, int, &record:id>
>,
boost::hashed_non_unique<
boost::multi_index::tag<type_tag>,
boost::multi_index::member<record, int, &record:type>
>
>
>;
我们现在可以从ID的唯一散列索引(常规散列映射,如unordered_map
)或类型的非唯一散列索引(如unordered_multimap
)访问数据使用数据视图。
record_container data;
// .... Fill with data
// Find by ID
auto& id_view = data.get<id_tag>();
auto id_it = id_view.find(15);
if (id_it == id_view.end()) {
// not found
} else {
// found
}
您也可以使用这样的容器创建复合键并轻松完成复杂逻辑:
using composite = boost::multi_index::composite_key<
record,
boost::multi_index::member<record, int, &record::id>,
boost::multi_index::member<record, int, &record::type>
>;
修改
如果你不能使用Boost,我有一个MultiIndex的分支,它使用C ++ 11的功能,不需要Boost。它完全取决于Brigand的一小部分,一个C ++ 11,模板元编程,仅头文件库。
答案 1 :(得分:0)
您可以使用类和容器及其迭代器。
class DB
{
private:
typedef list<Record>::iterator iterator;
list<Record> records;
iterator itForId;
public:
// return iterator of first record with id == parameter
iterator GetFirstForId(int id);
iterator GetNextForId(int id);
iterator end() {return records.end();}
};
删除记录会使迭代器混乱,因此最好将记录标记为删除,然后在不迭代容器时标记删除。
class DataRecord : public Record
{
bool markedForDeletion;
};