在 Swift 中递归更改字典中的某些键

Recursively change some keys in a Dictionary in Swift

我有字典

var dictionary: Any = ["det" : ["val" : "some","result" : ["key1" : "val1","key2" : "val2"],"key3" :["val1", "val2"]]]

下面还有一个映射函数

func getMappedKey(_ key: String) -> String? {
    var mapping: Dictionary = [
        "key1" : "key3",
        "key2" : "key4",
        "det" : "data"
    ]
    return mapping[key]
}

现在我想使用上面的映射函数更改同一个字典中的一些键。所以在改变之后,字典应该看起来像

["data" : ["val" : "some","result" : ["key3" : "val1","key4" : "val2"],"key3" :["val1", "val2"]]]

为此我在下面写了一个函数

func translatePayload(_ payload: inout Any) {
    if let _ = payload as? String {
        return
    } else if var payload = payload as? Dictionary<String, Any> {
        for (key, value) in payload {
            if let newKey = getMappedKey(key) {
                if let _ = payload.removeValue(forKey: key) {
                    payload[newKey] = value
                }
            }
            var nextPayload = value
            translatePayload(&nextPayload)
        }
    } else if let payload = payload as? Array<Any> {
        for value in payload {
            var nextPayload = value
            translatePayload(&nextPayload)
        }
    }
}

当我调用函数时

translatePayload(&dictionary)
print(dictionary)

它不会更改同一字典中的键。有人可以指出这段代码有什么问题吗?提前致谢

您的代码非常好,您只是更新了局部变量而不是参数变量,因为您使用了相同的名称。只需将局部变量 payload 更改为 dictionaryarray 或您喜欢的任何其他内容。

这是最终代码:

func translatePayload(_ payload: inout Any) {
    if let _ = payload as? String {
        return
    } else if var dictionary = payload as? Dictionary<String, Any> { // Here dictionary instead of payload
        for (key, value) in dictionary {
            var nextPayload = value
            translatePayload(&nextPayload)
            if let newKey = getMappedKey(key) {
                if let _ = dictionary.removeValue(forKey: key) {
                    dictionary[newKey] = nextPayload
                }
            } else {
                dictionary[key] = nextPayload
            }
        }
        payload = dictionary
    } else if let array = payload as? Array<Any> { // Here array instead of payload
        var updatedArray = array
        for (index, value) in array.enumerated() {
            var nextPayload = value
            translatePayload(&nextPayload)
            updatedArray[index] = nextPayload
        }
        payload = updatedArray // Assign the new changes
    }
}

translatePayload(&dictionary)
print(dictionary)

并不是对问题 "what's wrong" 的直接回答,但我会选择类似的内容:

let dictionary = ["det" : ["val" : "some","result" : ["key1" : "val1", "key2" : "val2"],"key3" :["val1", "val2"]]]

func getMapped(key: String) -> String {
    var mapping: Dictionary = [
        "key1" : "key3",
        "key2" : "key4",
        "det" : "data"
    ]
    return mapping[key] ?? key
}

func translate(payload:Any, map:(String)->String) -> Any {
    switch payload {
    case let value as String:
        return value
    case let value as [String:Any]:
        return value.reduce(into:[String:Any]()) {
            [=10=][map(.0)] = translate(payload: .1, map:map)
        }
    case let value as [Any]:
        return value.map { translate(payload: [=10=], map:map) }
    default:
        fatalError("Unknown data type")
    }
}

let output = translate(payload: dictionary, map:getMapped(key:))

真正利用 Swift 的功能精神。