鉴于,
let input = [
"A": ["X": 1, "Y": 2, "Z": 3],
"B": ["X": 7, "Y": 8, "Z": 9],
]
你是如何生产的,
[
"X": ["A": 1, "B": 7],
"Y": ["A": 2, "B": 8],
"Z": ["A": 3, "B": 9],
]
使用函数式编程?
答案 0 :(得分:4)
你可以这样做:
let input = ["A": ["X": 1, "Y": 2, "Z": 3], "B": ["X": 7, "Y": 8, "Z": 9]]
let output = input.flatMap { okv in
okv.value.map { ikv in
(ikv.key, okv.key, ikv.value)
}
}
.reduce(into: [String:[(String,Int)]]()) { accum, value in
accum[value.0] = (accum[value.0] ?? []) + [(value.1,value.2)]
}
.reduce(into: [String:[String:Int]]()) { accum, value in
accum[value.key] = value.value.reduce(into: [String:Int]()) { iaccum, ivalue in
iaccum[ivalue.0] = ivalue.1
}
}
首先将嵌套字典扩展为元组数组 [("X", "A", 1), ("Y", "A", 2), ... ]
,然后分两个阶段将该中间数组缩减回字典:首先作为数组字典,然后作为字典字典。< /p>
事实上,如果你利用默认的字典值,你可以做得更好:
let result = input.flatMap { okv in
okv.value.map { ikv in
(ikv.key, okv.key, ikv.value)
}
}
.reduce(into: [String:[String:Int]]()) { accum,value in
accum[value.0, default: [String:Int]()][value.1] = value.2
}
答案 1 :(得分:2)
我想出了类似下面的东西。我发现使用命令式方法比使用函数式编程更容易理解这个问题。
注意-:我没有涉及边缘情况。
class Test{
var outputDict:[String:[String:Int]] = [:]
func test(){
let input = ["A": ["X": 1, "Y": 2, "Z": 3], "B": ["X": 7, "Y": 8, "Z": 9]]
for (key,val) in input{
var newDict:[String:Int] = [:]
for (key1,val1) in val{
generateInternalDict(&newDict, val1, key, key1)
}
}
print(outputDict)
}
func generateInternalDict(_ newDict:inout [String:Int],_ value:Int,_ keyOuter:String,_ keyInner:String){
if outputDict[keyInner] == nil{
newDict[keyOuter] = value
outputDict[keyInner] = newDict
}else{
var getDictForKey = outputDict[keyInner]
getDictForKey![keyOuter] = value
outputDict[keyInner] = getDictForKey
}
}
}
输出-:
<块引用>["X": ["B": 7, "A": 1], "Z": ["B": 9, "A": 3], "Y": ["B": 8 , "A": 2]]