Swift 3: Array to Dictionary?
Is that it (in Swift 4)?
let dict = Dictionary(uniqueKeysWithValues: array.map{ ($0.key, $0) })
Note: As mentioned in the comment, using uniqueKeysWithValues
would give a fatal error (Fatal error: Duplicate values for key: 'your_key':
) if you have duplicated keys.
If you fear that may be your case, then you can use init(_:uniquingKeysWith:)
e.g.
let pairsWithDuplicateKeys = [("a", 1), ("b", 2), ("a", 3), ("b", 4)]let firstValues = Dictionary(pairsWithDuplicateKeys, uniquingKeysWith: { (first, _) in first })let lastValues = Dictionary(pairsWithDuplicateKeys, uniquingKeysWith: { (_, last) in last })print(firstValues)//prints ["a": 1, "b": 2]print(lastValues)//prints ["a": 3, "b": 4]
I think you're looking for something like this:
extension Array { public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] { var dict = [Key:Element]() for element in self { dict[selectKey(element)] = element } return dict }}
You can now do:
struct Person { var name: String var surname: String var identifier: String}let arr = [Person(name: "John", surname: "Doe", identifier: "JOD"), Person(name: "Jane", surname: "Doe", identifier: "JAD")]let dict = arr.toDictionary { $0.identifier }print(dict) // Result: ["JAD": Person(name: "Jane", surname: "Doe", identifier: "JAD"), "JOD": Person(name: "John", surname: "Doe", identifier: "JOD")]
If you'd like your code to be more general, you could even add this extension on Sequence
instead of Array
:
extension Sequence { public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] { var dict: [Key:Iterator.Element] = [:] for element in self { dict[selectKey(element)] = element } return dict }}
Do note, that this causes the Sequence to be iterated over and could have side effects in some cases.
On Swift 4, you can achieve this by using Dictionary's grouping:by:
initializer
For ex: You have class named A
class A { var name: String init(name: String) { self.name = name } // . // . // . // other declations and implementions}
Next, you have an array of objects of type A
let a1 = A(name: "Joy")let a2 = A(name: "Ben")let a3 = A(name: "Boy")let a4 = A(name: "Toy")let a5 = A(name: "Tim")let array = [a1, a2, a3, a4, a5]
Let's say you want to create a Dictionary by grouping all the names by their first letter. You use Swifts Dictionary(grouping:by:)
to achieve this
let dictionary = Dictionary(grouping: array, by: { $0.name.first! })// this will give you a dictionary// ["J": [a1], "B": [a2, a3], "T": [a4, a5]]
Note however that the resulting Dictionary "dictionary" is of type
[String : [A]]
it is not of type
[String : A]
as you may expect. (Use #uniqueKeysWithValues
to achieve the latter.)