如何快速更新嵌套字典

时间:2019-03-21 15:27:59

标签: swift dictionary

我有嵌套的字典,所以像这样:

var dict = ["a":["b":"c", "d":["e":"f"]], "f":["b":"g"]] // and more

现在,如果我想更新密钥a.d.e的值,该怎么办?

似乎updateValue方法仅按原样读取键...对嵌套键一无所知。

编辑:

虽然我确实想将这些数据的结构更改为更易于使用的结构。我不能这属于另一个类,我不允许更改结构,我所能做的就是更新它。

第二次修改:

经过一番思考并读完另一个问题,有人指出可能是重复的,尝试递归更新。我认为这是最糟糕的方法,因为从本质上讲,它正在使用原始值的副本创建新字典并将其分配回去。我确实认为这是浪费空间,并且甚至递归地调用它,我觉得这是不必要的。

func updateKey(key:[AnyHashable],val:Bool,data:[AnyHashable:Any])->[AnyHashable:Any]{
var keyTemp = key
var tempData = data

if(keyTemp.count==1){
    tempData.updateValue(val, forKey: key[0])
    print(tempData)
    return tempData

}else{
    var firstLayerValue = data[keyTemp[0]] as? [AnyHashable:Any]
    var firstKey = keyTemp.removeFirst()
    var tempResult = updateKey(key: keyTemp, val: val, data: firstLayerValue!)
    tempData.updateValue(tempResult, forKey: firstKey)
    return tempData;
    }
}

这将返回我要执行的操作的副本,并且我必须将其实际分配回原始副本。我真的不喜欢这种来回分配的东西,如果中间出现问题,那我可能最终会丢失最初正确的数据。

有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

结构是必经之路。但是,如果您真的必须使用字典,可以采用以下解决方法:

var dict: [AnyHashable: Any] =
    ["a": ["b": "c", "d": ["e":"f"]],
     "f": ["b": "g"]]

let newValue = true

if var firstLevel = dict["a"] as? [String : Any],
    var secondLevel = firstLevel["d"] as? [String: Any] {
    secondLevel["e"] = newValue
    firstLevel["d"] = secondLevel
    dict["a"] = firstLevel
}

print(dict)  //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]

要更新具有多个级别的字典中的值,可以定义如下函数:

func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any) {

    if keys.count < 2 {
        for key in keys { dict[key] = value }
        return
    }

    var levels: [[AnyHashable: Any]] = []

    for key in keys.dropLast() {
        if let lastLevel = levels.last {
            if let currentLevel = lastLevel[key] as? [AnyHashable: Any] {
                levels.append(currentLevel)
            }
            else if lastLevel[key] != nil, levels.count + 1 != keys.count {
                break
            } else { return }
        } else {
            if let firstLevel = dict[keys[0]] as? [AnyHashable : Any] {
                levels.append(firstLevel )
            }
            else { return }
        }
    }

    if levels[levels.indices.last!][keys.last!] != nil {
        levels[levels.indices.last!][keys.last!] = value
    } else { return }

    for index in levels.indices.dropLast().reversed() {
        levels[index][keys[index + 1]] = levels[index + 1]
    }

    dict[keys[0]] = levels[0]
}

并像这样使用它:

var dict: [AnyHashable: Any] = ["a": ["b": 1,
                                      "c": ["d": ["e": "f"],
                                            "g": ["h": 1.5]]],
                                "j": ["k": 2]]

update(dictionary: &dict,
       at: ["a", "c", "d", "e"],
       with: true)

dict.forEach { print($0) }

这是控制台中的输出:

(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])

答案 1 :(得分:1)

另一种方式

dict["a"]?["d"] = ["e": 123]
print(dict)

输出

  

[“ f”:[“ b”:“ g”],“ a”:[“ b”:“ c”,“ d”:[“ e”:123]]]