識別できるオブジェクトの配列があり、それから辞書を作成したいとします。次のようにして、配列からタプルを簡単に取得できます。
let tuples = myArray.map { return ($0.id, $0) }
しかし、タプルの配列を取得するためのディクショナリの初期化子が見えません。何か不足していますか?この機能のために辞書の拡張機能を作成しましたか(実際には難しくありませんが、デフォルトで提供されると思いました)、それを行う簡単な方法はありますか?
拡張用のコードがあります
extension Dictionary
{
public init (_ arrayOfTuples : Array<(Key, Value)>)
{
self.init(minimumCapacity: arrayOfTuples.count)
for Tuple in arrayOfTuples
{
self[Tuple.0] = Tuple.1
}
}
}
Swift 4
タプルが(Hashable、String)の場合、次のように使用できます。
let array = [("key1", "value1"), ("key2", "value2"), ("key3", "value3")]
let dictionary = array.reduce(into: [:]) { $0[$1.0] = $1.1 }
print(dictionary) // ["key1": "value1", "key2": "value2", "key3": "value3"]
作成には、ネイティブディクショナリのinit関数を使用できます。
Dictionary(uniqueKeysWithValues: [("a", 0), ("b", 1)])
// ["b": 1, "a": 0]
Dictionary(uniqueKeysWithValues: [("a", 0), ("b", 1), ("b", 2)])
// Fatal error: Duplicate values for key: 'b'
// takes the first match
Dictionary([("a", 0), ("b", 1), ("a", 2)], uniquingKeysWith: { old, _ in old })
// ["b": 1, "a": 0]
// takes the latest match
Dictionary([("a", 0), ("b", 1), ("a", 2)], uniquingKeysWith: { $1 })
// ["b": 1, "a": 2]
また、ショートカットが必要な場合:
Dictionary([("a", 0), ("b", 1), ("a", 2)]) { $1 }
何をしたいかに応じて、次のことができます。
let tuples = [(0, "0"), (1, "1"), (1, "2")]
var dictionary = [Int: String]()
オプション1:既存のキーを置き換える
tuples.forEach {
dictionary[$0.0] = $0.1
}
print(dictionary) //prints [0: "0", 1: "2"]
オプション2:繰り返しキーを許可しない
enum Errors: Error {
case DuplicatedKeyError
}
do {
try tuples.forEach {
guard dictionary.updateValue($0.1, forKey:$0.0) == nil else { throw Errors.DuplicatedKeyError }
}
print(dictionary)
} catch {
print("Error") // prints Error
}
/**
* Converts tuples to dict
*/
func dict<K,V>(_ tuples:[(K,V)])->[K:V]{
var dict:[K:V] = [K:V]()
tuples.forEach {dict[$0.0] = $0.1}
return dict
}
関数型プログラミングの更新:
func dict<K,V>(tuples:[(K,V)])->[K:V]{
return tuples.reduce([:]) {
var dict:[K:V] = $0
dict[$1.0] = $1.1
return dict
}
}
拡張機能を使用した@GitSync応答の改善。
extension Array {
func toDictionary<K,V>() -> [K:V] where Iterator.Element == (K,V) {
return self.reduce([:]) {
var dict:[K:V] = $0
dict[$1.0] = $1.1
return dict
}
}
}
@Stefan回答の更新。
extension Array {
func toDictionary<K, V>() -> [K: V] where Iterator.Element == (K, V) {
return Dictionary(uniqueKeysWithValues: self)
}
}