我有一个快速的字典[String:Any],我将它存储在UserDefauls中作为数组[[String:Any]]
我想做的是用另一个替换键:value,例如"id": "x:coredataid"
与"id": "server id"
我需要先遍历数组,然后遍历所有键值。为此有什么优雅的解决方案吗?
如果不是,那么如何简单地遍历字典中的所有键值和所有嵌套级别?
我有此代码:for (key, value) in params
但这仅适用于顶级密钥。
让我详细解释一下。如您所见,我有phases
键,它是一个数组。此外,每个phase
都包含day
键,它也是一个数组。
因此,我实际上并不关心密钥的命名,分阶段还是几天,是否要迭代所有密钥,提供的[String:Any]字典中的值并检查密钥是否包含等于提供的字符串的值
如您所见,当前trainingId等于:<x-coredata://C3C82F5A-8709-4EDC-8AE5-C23C65F220D5/WorkoutEntity/t072831FB-8F5C-4589-85CB-6D084671C097815>
我用红线下划线。
所以我想循环字典以捕获此关键的ExerciseId并检查其是否等于<x-coredata://C3C82F5A-8709-4EDC-8AE5-C23C65F220D5/WorkoutEntity/t072831FB-8F5C-4589-85CB-6D084671C097815>
我再也不在乎workoutId
的名称了,密钥实际上可以命名为exerciseId
或id不用担心。我只想在整个字典中找到一个值<x-coredata://C3C82F5A-8709-4EDC-8AE5-C23C65F220D5/WorkoutEntity/t072831FB-8F5C-4589-85CB-6D084671C097815>
,如果有很多func update(_ dict: [String: Any], set serverId: Any, for localId: String) -> [String: Any] {
var newDict = dict
for (k, v) in newDict {
if let mobileLocalId = v as? String {
if mobileLocalId == localId {
newDict[k] = serverId
} else { newDict[k] = v }
} else if let subDict = v as? [String: Any] {
newDict[k] = update(subDict, set: serverId, for: localId)
} else if let dictionaries = v as? [[String: Any]] {
for dictionary in dictionaries {
newDict[k] = update(dictionary, set: serverId, for: localId)
}
}
}
return newDict
}
,请全部替换。
我需要它连接到标识符的原因是,我存储的本地语言等于您注意到的CoreData标识符。但是,当我用从服务器返回的新标识符修改CoreData记录时,我想用新ID替换我的UserDefaults离线请求存储。
我还对此代码进行了修改:
(lldb) po newDict
▿ 2 elements
▿ 0 : 2 elements
- key : "position"
- value : 0
▿ 1 : 2 elements
- key : "workoutId"
- value : "5d51723b3faceb53f9d2d5ed"
但是对于我和newDict来说,它却以某种方式下降了几天:
context.startForegroundService(serviceIntent);
mainThreadHdlr = hdlr;
我确实在哪里成功更改了标识符,但是现在遗漏了上面示例中的所有其他键对。
答案 0 :(得分:2)
此递归函数将遍历所有键值:
func iterateThroughAllKeyValues<Key: Hashable, Value>(of dictionary: Dictionary<Key, Value>, execute execution: ((Key, Value))->()) {
for element in dictionary {
if let dictionary = element.value as? [Key: Value] {
iterateThroughAllKeyValues(of: dictionary, execute: execution)
} else {
execution(element)
}
}
}
通过一点点更改,您也可以在任何嵌套字典的主节点上调用execution
。
这是扩展模式:
extension Dictionary {
func iterateThroughAllKeyValues(execute execution: ((Key, Value))->()) {
for element in self {
if let dictionary = element.value as? [Key: Value] {
dictionary.iterateThroughAllKeyValues(execute: execution)
} else {
execution(element)
}
}
}
}
注意:请注意订单
用法示例:
let dictionary: [String: Any] = [
"id0": "value0",
"nested": ["id1": "value1"],
"nestedNested": ["id2": "value2",
"nested": ["id3": "value3"]]
]
dictionary.iterateThroughAllKeyValues { (key, value) in
print("key:", key, "Value:", value)
}
输出:
键:id0值:value0
键:id1值:value1
键:id3值:value3
键:id2值:value2
答案 1 :(得分:1)
这是一个具有递归功能的解决方案,该功能可以替换给定键的所有值。
func update(_ dict: [String: Any], set value: Any, for key: String) -> [String: Any] {
var newDict = dict
for (k, v) in newDict {
if k == key {
newDict[k] = value
} else if let subDict = v as? [String: Any] {
newDict[k] = update(subDict, set: value, for: key)
} else if let subArray = v as? [[String: Any]] {
var newArray = [[String: Any]]()
for item in subArray {
newArray.append(update(item, set: value, for: key))
}
newDict[k] = newArray
}
}
return newDict
}
请注意,它不会检查现有值是什么类型,而是直接将其替换为新值。此外,代码还假定嵌套数组的唯一类型是字典数组。
对于数组,此功能可以与map
一起使用
let out = data.map { update($0, set: "newValue", for: "id")}