The lesser-known Dictionary initializers in Swift

Subscribe to my newsletter and never miss my upcoming articles

Hello witches and werewolfs, Leo here.

Today we'll explore some Swift Standard Library. Today the topic is about the lesser known Dictionary initializers, recently I discovered that Dictionaries in Swift has 7, yes you read it right, SEVEN different initializers that you can take advantage on your day to day tasks to improve your code readability and maintainability. We'll dive into some of those and let's see what we can learn from them.

The artists of the cover painting is Edward Percy Moran he was an American artist known for his scenes of American history.

Let's go.

[1:"Problem"]

You have two lists and you want to merge into a single key-value structure like a dictionary.

For the first problem we have two lists, the name list and the age list.

let nameList = ["Leo", "ana", "manzoni", "jonas"]
let ageList = [30, 26, 32, 44]

How can you merge those two lists into a single dictionary? You can traverse each index with a for x in 0..nameList.count and put the X index in each dictionary position OR you can use the dictionary initializer uniqueKeysWithValues like this:

let nameAgeDictionary = Dictionary(uniqueKeysWithValues: zip(nameList, ageList))

The zip function returns an array of tuples and this you can use to make your dictionary. Getting the result:

Screen Shot 2021-02-11 at 08.17.00.png

But remember the precondition to use this initializer is that you don't have duplicate keys in your key list to be merged, it'll throw an error saying you "have duplicate values for key: xxxx". To avoid this just guarantee that the count of each list is the same. You can also use a list of tuples to create your dictionary that the result is the same. And the order is not guaranteed in the result. Example:

let nameAgeList = [("leo",30),("ana",26),("manzoni",33)]
let nameAgeDictionary2 = Dictionary(uniqueKeysWithValues: nameAgeList)

[2:"Problem"]

You want to avoid RAM reallocation in your data structures.

If you have an idea of how much key-value pairs your dictionary will hold, you can initialize with the minimum capacity:

let myDictionary = Dictionary<String,Int>(minimumCapacity: 50) // vanilla syntax
let myDictionary2 = [String:Int](minimumCapacity: 50) // sugar syntax
let myDictionary3: Dictionary = [String:Int](minimumCapacity: 50) // vanilla sugar syntax (?)(lol)

Just remember, you will use this only you already have a vague idea of how much your data structure will use at least. This is a little performance tweek so use it only when you are sure of what you are doing.

[3:"Problem"]

You have lists where it might has duplicate keys.

Let's make another example now. Imagine that you are working in a log system, and the you always want the last modified date of the file. Now you have two lists, the fileList and the timestamp list:

let fileList = ["file1", "file2", "file1", "file3", "file2"]
let timestampList = [30, 20, 44, 222, 87] // imagine this are dates

But notice, the file list has duplicate values for files 1 and 2. And your task is the get only the last one of each. So you can use the Dictionary initializer called uniquingKeysWith as below:

let filesTimestampDictionary = Dictionary<String,Int>(zip(fileList, timestampList)) { 
(first, second) -> Int in // 1
    second // 2
}

print(filesTimestampDictionary)

At 1 mark you capture the first and the second parameters that represent the first key found and the second found and the 2 mark you choose what of the key will be in the result dict. And you can pick the first appearance too, just return the first in the closure. The result is:

Screen Shot 2021-02-11 at 08.44.02.png

As you can see, the result dictionary only has the file1 = 44 and file2 = 87. The order is not guaranteed in the result, so if you want order you''ll need to sort your dictionary first.

[4:"Problem"]

Imagine you have a list of students ages and you want to how many different ages are there.

Now the problem is about grouping things. This is a very interesting topic so let's explore some possibilities. Let's start with the students example:

let studentsAgeList = [3,5,5,2,9,9,10,12,2,5] // don't need to be ordered
let ageGroupedList = Dictionary(grouping: studentsAgeList) { $0 } // here is where the magic happens

print("We have \(studentsAgeList.count) students and \(ageGroupedList.count) different ages ")

Generating the result:

Screen Shot 2021-02-11 at 09.05.26.png

And you can use this grouping for everything. Like the problem with socks that will only have to count how many keys have value of two.

You can use it to group Strings. Imagine you have a list of cities and you want to group them by the first letter:

let cityList = ["Santo Andre", "Maua", "Diadema", "San Paolo",
                "Salvador", "Natal", "Diamantina" , "Monte Verde"]
let cityGroupedList = Dictionary(grouping: cityList) { $0.first! }

print(cityGroupedList)

With this amazing result:

Screen Shot 2021-02-11 at 09.16.47.png

And you can have more extravagant uses like if you need to group the cityList by the last letter of the alphabet they use in their name. Example:

let cityList = ["Santo Andre", "Maua", "Diadema", "San Paolo",
                "Salvador", "Natal", "Diamantina" , "Monte Verde"]
let cityGroupedList = Dictionary(grouping: cityList) { $0.max()! }

print(cityGroupedList)

Resulting in this:

Screen Shot 2021-02-11 at 09.22.14.png

Conclusion

This adventure in the realms of the Dictionary tells us just one thing: It's always good to know the basics of the language to avoid complicated and unnecessary coding. Until today I didn't know a lot of those and was a very good time learning and studying this, I hope you enjoyed as I do.

Any thoughts or comments please don't hesitate to share below.

Thanks for the reading and... That's all folks!

credit: image

No Comments Yet