Я припускаю, що проблема полягає в тому, щоб зберегти ключі нашого оригінального словника і якось відобразити всі його значення.
Давайте узагальнимо і скажемо, що ми можемо захотіти перенести всі значення до іншого типу .
Отже, з чого ми хотіли б почати - це словник і закриття (функція), а в кінцевому підсумку новий словник. Проблема полягає, звичайно, у тому, що Суіфт чітко вводить текст. При закритті потрібно вказати, який тип входить і який тип виходить, і, таким чином, ми не можемо зробити метод, який займає загальне закриття - за винятком загального контексту. Таким чином, нам потрібна родова функція.
Інші рішення зосереджуються на тому, щоб це зробити в загальному світі самої родової структури словника, але мені легше думати з точки зору функції вищого рівня. Наприклад, ми могли б написати це, де K - тип ключа, V1 - тип значення стартового словника, а V2 - тип значення кінця словника:
func mapValues<K,V1,V2>(d1:[K:V1], closure:(V1)->V2) -> [K:V2] {
var d2 = [K:V2]()
for (key,value) in zip(d1.keys, d1.values.map(closure)) {
d2.updateValue(value, forKey: key)
}
return d2
}
Ось простий приклад його виклику, лише щоб довести, що загальне дійсно вирішує себе під час компіляції:
let d : [String:Int] = ["one":1, "two":2]
let result = mapValues(d) { (i : Int) -> String in String(i) }
Ми почали зі словника [String:Int]
і закінчили словником [String:String]
, трансформуючи значення першого словника через закриття.
(EDIT: Тепер я бачу, що це фактично те саме, що рішення AirspeedVelocity, за винятком того, що я не додав додаткової елегантності ініціалізатора словника, який створює словник із zip-послідовності.)