Swift:将一个字典数组展平为一个字典

Lne*_*ner 13 arrays dictionary functional-programming flatmap swift

在Swift中,我试图将一系列字典拼成一个字典,即

let arrayOfDictionaries = [["key1": "value1"], ["key2": "value2"], ["key3": "value3", "key4": "value4"]]


//the end result will be:   
 flattenedArray = ["key1": "value1", "key2": "value2", "key3": "value3", "key4": "value4"]
Run Code Online (Sandbox Code Playgroud)

我尝试过使用flatmap,但返回结果的类型是,[(String, AnyObject)]而不是[String, Object]ie

let flattenedArray = arrayOfDictionaries.flatMap { $0 }
// type is [(String, AnyObject)]
Run Code Online (Sandbox Code Playgroud)

所以我有两个问题:

  • 为什么返回类型[(String,AnyObject)]?括号是什么意思?

  • 我如何达到预期的效果?

编辑:我更喜欢使用Swift的map/flatmap/reduce等功能方法而不是for-loop

das*_*ght 15

括号是什么意思?

这个以及逗号而不是冒号应该提供第一个线索:括号意味着你得到一个元组数组.由于您正在寻找字典而不是数组,这告诉您需要将元组序列(键值对)转换为单个字典.

我如何达到预期的效果?

一种方法是使用reduce,如下所示:

let flattenedDictionary = arrayOfDictionaries
    .flatMap { $0 }
    .reduce([String:String]()) { (var dict, tuple) in
        dict.updateValue(tuple.1, forKey: tuple.0)
        return dict
    }
Run Code Online (Sandbox Code Playgroud)

  • @Lneuner因为map/flatMap迭代字典.当字典被迭代时,字典中的每个项目都作为`(key,value)`元组返回.这在文档底部描述[here](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html). (2认同)

Mar*_*ars 7

更新@dasblinkenlight对Swift 3的回答.

参数中的"var"已被弃用,但这种方法对我来说很好.

let flattenedDictionary = arrayOfDictionaries
    .flatMap { $0 }
    .reduce([String:String]()) { (dict, tuple) in
        var nextDict = dict
        nextDict.updateValue(tuple.1, forKey: tuple.0)
        return nextDict
    }
Run Code Online (Sandbox Code Playgroud)


Ima*_*tit 7

使用Swift 4,Dictionay有一个init(_:uniquingKeysWith:)初始化程序.init(_:uniquingKeysWith:)有以下声明:

init<S>(_ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows where S : Sequence, S.Element == (Key, Value)
Run Code Online (Sandbox Code Playgroud)

从给定序列中的键值对创建新字典,使用组合闭包来确定任何重复键的值.


以下两个Playground代码片段展示了如何将一个字典数组展平为一个新字典.

let dictionaryArray = [["key1": "value1"], ["key1": "value5", "key2": "value2"], ["key3": "value3"]]

let tupleArray: [(String, String)] = dictionaryArray.flatMap { $0 }
let dictonary = Dictionary(tupleArray, uniquingKeysWith: { (first, last) in last })

print(dictonary) // prints ["key2": "value2", "key3": "value3", "key1": "value5"]
Run Code Online (Sandbox Code Playgroud)
let dictionaryArray = [["key1": 10], ["key1": 10, "key2": 2], ["key3": 3]]

let tupleArray: [(String, Int)] = dictionaryArray.flatMap { $0 }
let dictonary = Dictionary(tupleArray, uniquingKeysWith: { (first, last) in first + last })
//let dictonary = Dictionary(tupleArray, uniquingKeysWith: +) // also works

print(dictonary) // ["key2": 2, "key3": 3, "key1": 20]
Run Code Online (Sandbox Code Playgroud)

  • 为什么这些Swift 4功能是为“从(键,值)元组的序列初始化”而不是(或者)“字典序列”而构建的?这迫使在代码中包含“ tupleArray”步骤,这很烦人。 (2认同)