Как создать словарь из массива кортежей?

Давайте скажем, что у меня есть массив объектов, которые можно идентифицировать, и я хочу создать словарь из него. Я легко могу получить кортежи из своего массива следующим образом:

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
        }
    }
}

Ответ 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"]

Ответ 2

В зависимости от того, что вы хотите сделать, вы можете:

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
}

Ответ 3

Общий подход:

/**
 * 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
    }
}

Ответ 4

Swift 4

Для создания вы можете использовать родные функции словаря инициализации:

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 }

Ответ 5

Улучшен ответ @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
        }
    }
}