Начиная со Swift 4, это можно сделать очень легко. Есть два новых инициализатора, которые создают словарь из последовательности кортежей (пары ключ и значение). Если ключи гарантированно уникальны, вы можете сделать следующее:
let persons = [Person(name: "Franz", position: 1),
Person(name: "Heinz", position: 2),
Person(name: "Hans", position: 3)]
Dictionary(uniqueKeysWithValues: persons.map { ($0.position, $0.name) })
=> [1: "Franz", 2: "Heinz", 3: "Hans"]
Это приведет к ошибке выполнения, если какой-либо ключ дублируется. В этом случае вы можете использовать эту версию:
let persons = [Person(name: "Franz", position: 1),
Person(name: "Heinz", position: 2),
Person(name: "Hans", position: 1)]
Dictionary(persons.map { ($0.position, $0.name) }) { _, last in last }
=> [1: "Hans", 2: "Heinz"]
Это ведет себя как ваш цикл for. Если вы не хотите «перезаписывать» значения и придерживаться первого сопоставления, вы можете использовать это:
Dictionary(persons.map { ($0.position, $0.name) }) { first, _ in first }
=> [1: "Franz", 2: "Heinz"]
Swift 4.2 добавляет третий инициализатор, который группирует элементы последовательности в словарь. Ключи словаря выводятся замыканием. Элементы с одинаковым ключом помещаются в массив в том же порядке, что и в последовательности. Это позволяет достичь результатов, аналогичных приведенным выше. Например:
Dictionary(grouping: persons, by: { $0.position }).mapValues { $0.last! }
=> [1: Person(name: "Hans", position: 1), 2: Person(name: "Heinz", position: 2)]
Dictionary(grouping: persons, by: { $0.position }).mapValues { $0.first! }
=> [1: Person(name: "Franz", position: 1), 2: Person(name: "Heinz", position: 2)]
[position:name]или[position:[name]]? Если у вас есть два человека в одной позиции, ваш словарь сохранит только последний из встреченных в вашем цикле ... У меня есть аналогичный вопрос, для которого я пытаюсь найти решение, но я хочу, чтобы результат был похож на[1: [p1, p3], 2: [p2]]