我使用QVariant
来管理内部应用程序的项目设置。
为此,我使用了一个嵌套的QVariantMap
,递归地包含QVariantMap
s和保持实际值的叶。
现在,我发现从这个树状结构中设置和删除节点非常麻烦。尤其是当嵌套达到一定深度时。
部分问题在于,value<T>
返回的是副本而不是引用。(我想知道,为什么Qt没有这个功能?(
#include <QVariantMap>
#include <QDebug>
int main(int argc, char** args) {
QVariantMap map = { {"A", QVariantMap{ {"B",5.} }} };
{
// Change value
auto nested = map["A"].value<QVariantMap>();
nested["B"] = 6;
map["A"] = nested;
qDebug() << map;
// What it should be
// map["A"]["B"] = 5;
}
{
// Remove value
auto nested = map["A"].value<QVariantMap>();
nested.remove("B");
map["A"] = nested;
qDebug() << map;
// What it should be
// map["A"].remove("B");
}
}
直接设置和删除值以及使我的函数成为一行函数的最简单方法是什么?性能并不重要,但易用性对我来说绝对是个问题
经过一番思考,我想出了使用一条路径来获取所需值的想法。此路径应该是唯一的。
下面的代码递归地查找值并将其删除。更改值应该非常类似。我不确定是否有更简单的方法。
bool remove(QVariantMap& map, const QString& path, QString sep = ".") {
auto elems = path.split(sep);
if (elems.size() > 1) {
if (!map.contains(elems.first())) return false;
auto tmp = elems;
tmp.pop_front();
auto childMap = map[elems.first()].value<QVariantMap>();
bool ret = remove(childMap, tmp.join("."));
if (!ret) return false;
map[elems.first()] = childMap;
return true;
}
else if (elems.size() == 1) {
return map.remove(elems[0]) >= 1;
}
else {
return false;
}
}
备注
如果有大量数据,则不应使用此解决方案,因为有相当多的地图复制。