Я хотел бы отобразить функцию на все ключи в словаре. Я надеялся, что что-то вроде следующего будет работать, но фильтр не может быть применен непосредственно к словарю. Какой самый чистый способ достижения этого?
В этом примере я пытаюсь увеличить каждое значение на 1. Однако это случайно для примера - основная цель - выяснить, как применить map () к словарю.
var d = ["foo" : 1, "bar" : 2]
d.map() {
$0.1 += 1
}
swift
dictionary
Мария Зверина
источник
источник
map
делает. то, что вы просите, - это способ скрыть итерацию за расширением / закрытием, чтобы вам не приходилось смотреть на нее каждый раз, когда вы ее используете.Ответы:
Свифт 4+
Хорошие новости! Swift 4 включает в себя
mapValues(_:)
метод, который создает копию словаря с одинаковыми ключами, но разными значениями. Он также включает в себяfilter(_:)
перегрузку, которая возвращает инициализаторы aDictionary
, andinit(uniqueKeysWithValues:)
иinit(_:uniquingKeysWith:)
для создания aDictionary
из произвольной последовательности кортежей. Это означает, что если вы хотите изменить и ключи, и значения, вы можете сказать что-то вроде:Есть также новые API для объединения словарей вместе, замены значения по умолчанию для отсутствующих элементов, группировки значений (преобразования коллекции в словарь массивов, основанный на результате сопоставления коллекции какой-либо функции) и многое другое.
Во время обсуждения предложения SE-0165 , в котором были представлены эти функции, я несколько раз поднимал этот ответ о переполнении стека, и я думаю, что огромное количество голосов помогло продемонстрировать спрос. Так что спасибо за вашу помощь, чтобы сделать Swift лучше!
источник
map
который может создавать конфликтующие ключи, все еще полезенmap
во многих ситуациях. (С другой стороны, вы могли бы утверждать, что отображение только значений является естественной интерпретациейmap
словарей - и пример исходного плаката, и мой пример только изменяют значения, а концептуальноmap
- только массив изменяет значения, а не индексы.)try
:return Dictionary<Key, OutValue>(try map { (k, v) in (k, try transform(v)) })
DictionaryExtension.swift:13:16: Argument labels '(_:)' do not match any available overloads
Argument labels '(_:)' do not match any available overloads
при реализации этого последнего расширения. Не совсем уверен, как это решить: /Dictionary
инициализатора, добавленного в одном из предыдущих примеров. Убедитесь, что вы включили их обоих.С Swift 5 вы можете использовать один из пяти следующих фрагментов , чтобы решить вашу проблему.
# 1. Используя
Dictionary
mapValues(_:)
метод# 2. Использование
Dictionary
map
метода иinit(uniqueKeysWithValues:)
инициализатора# 3. Используя
Dictionary
reduce(_:_:)
метод илиreduce(into:_:)
метод# 4. Используя
Dictionary
subscript(_:default:)
индекс# 5. Используя
Dictionary
subscript(_:)
индексисточник
В то время как большинство ответов здесь сосредоточены на том, как отобразить весь словарь (ключи и значения), вопрос на самом деле хотел только сопоставить значения. Это важное различие, поскольку сопоставление значений позволяет гарантировать одинаковое количество записей, тогда как сопоставление ключа и значения может привести к дублированию ключей.
Вот расширение,
mapValues
которое позволяет вам отображать только значения. Обратите внимание, что он также расширяет словарьinit
последовательностью пар «ключ / значение», которая является более общей, чем инициализация его из массива:источник
func mapValues<T>(_ transform: (_ value: Value) -> T) -> [Key: T] { var result = [Key: T]() for (key, val) in self { result[key] = transform(val) } return result }
. Я считаю, что это читается лучше тоже. Есть ли проблема с производительностью?Самый простой способ - просто добавить
map
в словарь:Проверка того, что это работает:
Вывод:
источник
SequenceType.map
это не мутирующая функция. Ваш пример может быть переписан с учетом существующего контрактаmap
, но это совпадает с принятым ответом.Вы также можете использовать
reduce
вместо карты.reduce
способен делать что угодноmap
может и больше!Было бы довольно легко обернуть это в расширение, но даже без расширения оно позволяет вам делать то, что вы хотите, одним вызовом функции.
источник
let newDict = oldDict.reduce([String:Int]()) { (var dict, pair) in dict["new\(pair.1)"] = pair.1; return dict }
Оказывается, вы можете сделать это. Что вам нужно сделать, это создать массив из
MapCollectionView<Dictionary<KeyType, ValueType>, KeyType>
возвращенного из словаряkeys
метода. ( Информация здесь ) Затем вы можете отобразить этот массив и передать обновленные значения обратно в словарь.источник
Согласно справочнику стандартной библиотеки Swift, карта является функцией массивов. Не для словарей.
Но вы можете перебрать свой словарь, чтобы изменить ключи:
источник
Я искал способ отобразить словарь прямо в типизированный массив с пользовательскими объектами. Нашел решение в этом расширении:
Используя это следующим образом:
источник
Swift 3
Я пробую легкий путь в Swift 3.
Я хочу , чтобы отобразить [String: String] к [String: String] , я использую Foreach вместо карты или плоской карте.
источник
Swift 5
Функция отображения словаря поставляется с этим синтаксисом.
dictData.map(transform: ((key: String, value: String)) throws -> T)
Вы можете просто установить значения закрытия для этого
Выход будет ::
Может быть, дать это предупреждение
Result of call to 'map' is unused
Затем просто установите
_ =
перед переменной.Может быть, это поможет вам Спасибо.
источник
Я предполагаю, что проблема заключается в том, чтобы сохранить ключи нашего исходного словаря и каким-то образом отобразить все его значения.
Давайте обобщим и скажем, что мы можем отобразить все значения в другой тип .
Итак, с чего мы хотели бы начать, это словарь и замыкание (функция) и в итоге новый словарь. Проблема, конечно, в том, что строгая типизация Swift мешает. Замыкание должно указывать, какой тип входит и какой тип получается, и поэтому мы не можем создать метод, который принимает общее замыкание - кроме как в контексте универсального. Таким образом, нам нужна общая функция.
Другие решения сконцентрировались на том, чтобы делать это в общем мире самой общей структуры словаря, но я считаю, что проще думать с точки зрения функции верхнего уровня. Например, мы могли бы написать это, где K - тип ключа, V1 - тип значения начального словаря, а V2 - тип значения конечного словаря:
Вот простой пример его вызова, просто чтобы доказать, что универсальный код действительно разрешает себя во время компиляции:
Мы начали со словаря
[String:Int]
и закончили со словарем[String:String]
, преобразовав значения первого словаря через замыкание.(РЕДАКТИРОВАТЬ: теперь я вижу, что это фактически то же самое, что решение AirspeedVelocity, за исключением того, что я не добавил дополнительную элегантность инициализатора словаря, который делает словарь из zip-последовательности.)
источник
Swift 3
Использование:
Расширение:
источник
Если вы только пытаетесь отобразить значения (потенциально меняя их тип), включите это расширение:
Если у вас есть этот словарь:
Преобразование значения в одну строку выглядит следующим образом:
Многострочная трансформация значений выглядит следующим образом:
источник
Другой подход заключается в том,
map
чтобы к словарю иreduce
, где функцииkeyTransform
иvalueTransform
функции.источник
Swift 3 Я использовал это,
Использование:
ссылка
источник