Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在swift中更新嵌套字典_Swift_Dictionary - Fatal编程技术网

如何在swift中更新嵌套字典

如何在swift中更新嵌套字典,swift,dictionary,Swift,Dictionary,我有嵌套字典,所以类似这样: var dict=[“a”:[“b”:“c”,“d”:[“e”:“f”],“f”:[“b”:“g”]//等等 现在,如果我想更新密钥a.d.e的值,我应该怎么做 似乎updateValue方法只按原样读取键…它对嵌套键一无所知 编辑: 虽然我真的想把这些数据的结构改成更容易处理的东西。我不能。这属于另一个类,我不允许更改结构,我所能做的就是更新它 第二次编辑: 经过一些思考和阅读另一个问题,有人指出可能是重复的,尝试递归更新。我觉得这真的是最糟糕的方法,因为从本质

我有嵌套字典,所以类似这样:

var dict=[“a”:[“b”:“c”,“d”:[“e”:“f”],“f”:[“b”:“g”]//等等
现在,如果我想更新密钥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;
    }
}
这将返回我打算执行的操作的副本,并且我必须实际将其分配回原始副本。我真的不喜欢这个分配来回的东西,如果中间出了什么差错,那么我可能最终会失去原来正确的数据。
有更好的解决方案吗?

结构是一条路要走。但如果你真的需要使用字典,这里有一个解决方法:

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": "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]
}
以下是控制台中的输出:


另一种方法

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

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


另一种方法

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

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


虽然这是可能的,但您应该在Swift中强烈避免这种数据结构。和他一起工作很尴尬。如果可能的话,把它转换成一个结构,这将使这个(和许多其他的麻烦)消失。如果您有专门的用例,有很多方法可以实现高度动态的数据结构,但是复杂的字典(尤其是包含
Any
anywhere的字典)通常不是合适的工具。您的数据是什么样子的?“我相信我们可以找到更好的数据结构。”安娜·乌奇。我以前去过那里。dict的结构每次都会完全相同吗?您可以为需要更新的各种值创建一个枚举,然后使用一个方法将枚举大小写作为参数,只需编写一个开关来处理要更新的各种值。哇…他们给了您一个非常糟糕的东西…键和值总是字符串吗?或者最终值类型可以是任意的?我有一些关于如何攻击它的想法,但是攻击最一般的情况是困难的;我需要考虑一下。这是一个…有趣的问题。(我指的是一个你不必面对的恼人的问题)虽然这是可能的,但你应该在Swift中强烈避免这种数据结构。和他一起工作很尴尬。如果可能的话,把它转换成一个结构,这将使这个(和许多其他的麻烦)消失。如果您有专门的用例,有很多方法可以实现高度动态的数据结构,但是复杂的字典(尤其是包含
Any
anywhere的字典)通常不是合适的工具。您的数据是什么样子的?“我相信我们可以找到更好的数据结构。”安娜·乌奇。我以前去过那里。dict的结构每次都会完全相同吗?您可以为需要更新的各种值创建一个枚举,然后使用一个方法将枚举大小写作为参数,只需编写一个开关来处理要更新的各种值。哇…他们给了您一个非常糟糕的东西…键和值总是字符串吗?或者最终值类型可以是任意的?我有一些关于如何攻击它的想法,但是攻击最一般的情况是困难的;我需要考虑一下。这是一个…有趣的问题。(我的意思是你不应该面对的一个恼人的问题。)评论中提到的OP,字典的类型是
[AnyHashable:Any]
评论中提到的OP,字典的类型是
[AnyHashable:Any]