如何在 C++/STL 中表示键值树
How can I represent a key-value-tree in C++ / STL
我尝试编写 键值对树 的表示形式,并可选择一个键的多个值。我尝试做的是在程序开始时读取 "data-tree",然后为程序的每个部分提供所需的 "branch" 数据。我目前使用的库是 OpenCV 和 Intel TBB。
XML 中的数据示例如下所示:
<key_1> value_1 </key_1>
<key_2> value_2 </key_2>
<!-- -->
<key_3>
<subkey_1> value_3 </subkey_1>
<subkey_2> value_4 value_5 value_6 </subkey_1>
</key_3>
<key_4> value_1 </key_4>
到目前为止我想到的是两个类:
- A Class 用于保存单个键值对,名为 KeyValue
- A Class KeyValueGroup 表示 KeyValues 的集合并且能够容纳其他 KeyValueGroups.
代码为:
class KeyValue {
std::string mKey;
std::vector<std::string> mValues;
}
class KeyValueGroup {
// setters, getters, etc
std::vector<KeyValue> mKeyValues;
std::vector<KeyValueGroup> mKeyValueGroups;
std::string mKey;
}
值可以是不同的类型,但我将它们转换为 std::string。我的解决方案有效,但我的直觉告诉我这个解决方案可能很尴尬。那么专业人士如何解决这个问题呢?
我问自己的另一个问题是,我是否应该将两个 类 包装在 std::shared_ptr 中以提高速度(平均字符串长度约为 5 个字符)。
您付出多少努力取决于此数据对您的程序的性能有多重要,您期望的 access/update 模式等。
对于要求不高的用途...
std::map<std::string, std::string> tree;
...其中 map
的键是 XML 指定键的串联,使用合适的分隔符或定界符(例如 space、'|'
, ';'
...?). std::unordered_map
是另一种选择。如果需要,可以写一个 "Key" class 来容纳一个 std::string
并提供一些方便的功能,例如剥离尾随元素等..
如果我需要更高级的东西,我会考虑第三方库,例如boost::graph
。有关 C++ 和树的背景,另请参阅 this question/answers。
您也可以使用 RapidJSON 文档对象。
这允许您用键和子键表示一个 JSON 对象。
这是一个例子:
rapidjson::Document document;
// Initialise the rapid json document to an empty object
document.SetObject();
Document::AllocatorType& allocator = document.GetAllocator();
// Add parent keys
document.AddMember("key_1", "value_1", allocator);
document.AddMember("key_2", "value_2", allocator);
document.AddMember("key_3", "value_3", allocator);
// Add subkeys
document["key_3"].SetObject();
document["key_3"].AddMember("subkey_1", "value_3", allocator);
我尝试编写 键值对树 的表示形式,并可选择一个键的多个值。我尝试做的是在程序开始时读取 "data-tree",然后为程序的每个部分提供所需的 "branch" 数据。我目前使用的库是 OpenCV 和 Intel TBB。
XML 中的数据示例如下所示:
<key_1> value_1 </key_1>
<key_2> value_2 </key_2>
<!-- -->
<key_3>
<subkey_1> value_3 </subkey_1>
<subkey_2> value_4 value_5 value_6 </subkey_1>
</key_3>
<key_4> value_1 </key_4>
到目前为止我想到的是两个类:
- A Class 用于保存单个键值对,名为 KeyValue
- A Class KeyValueGroup 表示 KeyValues 的集合并且能够容纳其他 KeyValueGroups.
代码为:
class KeyValue {
std::string mKey;
std::vector<std::string> mValues;
}
class KeyValueGroup {
// setters, getters, etc
std::vector<KeyValue> mKeyValues;
std::vector<KeyValueGroup> mKeyValueGroups;
std::string mKey;
}
值可以是不同的类型,但我将它们转换为 std::string。我的解决方案有效,但我的直觉告诉我这个解决方案可能很尴尬。那么专业人士如何解决这个问题呢?
我问自己的另一个问题是,我是否应该将两个 类 包装在 std::shared_ptr 中以提高速度(平均字符串长度约为 5 个字符)。
您付出多少努力取决于此数据对您的程序的性能有多重要,您期望的 access/update 模式等。
对于要求不高的用途...
std::map<std::string, std::string> tree;
...其中 map
的键是 XML 指定键的串联,使用合适的分隔符或定界符(例如 space、'|'
, ';'
...?). std::unordered_map
是另一种选择。如果需要,可以写一个 "Key" class 来容纳一个 std::string
并提供一些方便的功能,例如剥离尾随元素等..
如果我需要更高级的东西,我会考虑第三方库,例如boost::graph
。有关 C++ 和树的背景,另请参阅 this question/answers。
您也可以使用 RapidJSON 文档对象。
这允许您用键和子键表示一个 JSON 对象。 这是一个例子:
rapidjson::Document document;
// Initialise the rapid json document to an empty object
document.SetObject();
Document::AllocatorType& allocator = document.GetAllocator();
// Add parent keys
document.AddMember("key_1", "value_1", allocator);
document.AddMember("key_2", "value_2", allocator);
document.AddMember("key_3", "value_3", allocator);
// Add subkeys
document["key_3"].SetObject();
document["key_3"].AddMember("subkey_1", "value_3", allocator);