簡體   English   中英

Swift:在數組中組合字典

[英]Swift: Combine Dictionaries in an Array

我正在尋找一種優雅的方式來組合一系列字典。

Input: [[a: foo], [b: bar], [c: baz]]
Output: [a: foo, b: bar, c: baz]

實現這一目標的最佳方法是什么?

你可以使用reduce但是你必須定義一個“組合”方法,它可以為你提供一個來自2個單獨詞典的組合字典。

所以你可以這樣做

let inputArray = [["a": "foo"], ["b": "bar"], ["c": "baz"], ["c": "bazx"]]
let flat = inputArray.reduce([:]) { $0 + $1 }

如果你在Dictionary上重載了“+”

func + <K, V>(lhs: [K : V], rhs: [K : V]) -> [K : V] {
    var combined = lhs

    for (k, v) in rhs {
        combined[k] = v
    }

    return combined
}

這不是一個可怕的解決方案......

let inputArray = [["a": "foo"], ["b": "bar"], ["c": "baz"]]

let inputArrayFlat = inputArray.reduce([String:String]()) {
    var output = $0
    for (key, value) in $1 { output[key] = value }
    return output
}

我會使用Dictionary擴展名:

extension Dictionary {
    init<S: SequenceType where Element == S.Generator.Element>(_ s:S) {
        self.init()
        var g = s.generate()
        while let e: Element = g.next() {
            self[e.0] = e.1
        }
    }
}

使用此擴展,您可以使用一系列(Key, Value)對初始化Dictionary 所以你可以:

let input = [["a": "foo"], ["b": "bar"], ["c": "baz"]]

let output = Dictionary(input.reduce([], { $0 + $1 }))
let inputArray = [["a": "foo"], ["b": "bar"], ["c": "baz"]].reduce([], +)
var result:[String:String] = [:]
for item in inputArray {
    result.updateValue(item.1, forKey: item.0)
}
println(result.description)
let inputArray = [["a": "foo"], ["b": "bar"], ["c": "baz"], ["c": "bazx"]]

var flat = [String:String]()
for e in inputArray {
    for (k, v) in e {
        flat[k] = v
    }
}

dump(flat)

使用Swift 4.2的另一種方法:

let inputArray = [["a": "foo"], ["b": "bar"], ["c": "baz"], ["c": "bazx"]]
let result = inputArray.flatMap { $0 }.reduce([:]) { $0.merging($1) { (current, _) in current } }

輸出:

["b": "bar", "c": "baz", "a": "foo"]

你可以在外部數組上使用reduce兩次,在內部字典上使用一次,因為它們會被處理。 如果任何字典具有重復鍵,則此版本將僅保留該鍵的最后一個值。

func flattenDictionaryList<T, U>(list: [[T: U]]) -> [T: U] {
    return list.reduce([:]) { combined, current in
        reduce(current, combined) { (var innerCombined: [T: U], innerCurrent: (key: T, value: U)) in
            innerCombined[innerCurrent.key] = innerCurrent.value
            return innerCombined
        }
    }
}

let input = [["a": "foo"], ["b": "bar"], ["c": "baz"]]
let output = flattenDictionaryList(input)

將一組字典合並到一個字典中,用新密鑰覆蓋重復的現有密鑰。

[[String:String]]轉換為單個[String:String]

extension Array where Element == [String:String] {

    func merged() -> [String:String] {
        return reduce(into: [String:String]()) {
            $0.merge($1) { (_, new) in new }
        }
    }

}

我想要一個不依賴於String的泛型版本,但我很難將它表達給編譯器。 如果有人想要去做,請編輯或評論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM