Я предполагаю, что проблема заключается в том, чтобы сохранить ключи нашего исходного словаря и каким-то образом отобразить все его значения.
Давайте обобщим и скажем, что мы можем отобразить все значения в другой тип .
Итак, с чего мы хотели бы начать, это словарь и замыкание (функция) и в итоге новый словарь. Проблема, конечно, в том, что строгая типизация Swift мешает. Замыкание должно указывать, какой тип входит и какой тип получается, и поэтому мы не можем создать метод, который принимает общее замыкание - кроме как в контексте универсального. Таким образом, нам нужна общая функция.
Другие решения сконцентрировались на том, чтобы делать это в общем мире самой общей структуры словаря, но я считаю, что проще думать с точки зрения функции верхнего уровня. Например, мы могли бы написать это, где 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], преобразовав значения первого словаря через замыкание.
(РЕДАКТИРОВАТЬ: теперь я вижу, что это фактически то же самое, что решение AirspeedVelocity, за исключением того, что я не добавил дополнительную элегантность инициализатора словаря, который делает словарь из zip-последовательности.)