从深层嵌套的 QVariant 中更改和删除值

Ale*_*ph0 5 qt qvariant qmap

QVariant用来管理我们内部应用程序的项目设置。

为此,我使用嵌套QVariantMap递归包含QVariantMaps 并保留实际值。

现在,我发现从这个树状结构中设置和删除节点非常麻烦。特别是,如果嵌套达到一定深度。

部分问题是,它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");
    }
}
Run Code Online (Sandbox Code Playgroud)

直接设置和删除值并使我的函数成为单行函数的最简单方法可能是什么?性能并不重要,但易用性对我来说绝对是一个问题。

Ale*_*ph0 0

经过一番思考,我想到了使用一条通往我想要的价值的路径。这条路径应该是唯一的。

以下代码递归地查找该值并将其删除。更改值应该非常相似。我不确定是否有更简单的方法。

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

评论

如果有大量数据,则不应使用此解决方案,因为存在大量地图复制。