© Yanis Zafirópulos 2019
Yanis ZafirópulosSwift 4 Recipeshttps://doi.org/10.1007/978-1-4842-4182-0_9

9. Dictionaries

Yanis Zafirópulos1 
(1)
Granada, Spain
 

In programming, a dictionary is a general-purpose data structure, used to store a group of objects, in a “real” dictionary-like lemma-definition approach - or as group of key-value pairs, properly put.

In this chapter, we’ll explore most of Swift’s dictionary-related capabilities and learn how to create new ones, add/remove keys, merge them, and move on to even more advanced topics, such as handling property lists.

9.1 Add key-value pair to dictionary

Problem

I want to add a key-value pair to an existing dictionary

Solution

Let’s initialize our test dictionary.
var user = [
      "name"         : "John",
      "surname"      : "Doe",
      "email"        : "[email protected]"
]
OK, let’s add some more info.
user["nationality"] = "US"
And print the result...
print("User: (user)")

How It Works

A dictionary is a collection of key-value pairs. In order to add another key with a value, we can do it pretty much like changing an already existing key, that is: by using the subscript along with the value’s key and assign it the desired value.
User: ["name": "John", "surname": "Doe", "email": "[email protected]", "nationality": "US"]

9.2 Check if dictionary is empty

Problem

I want to check if a dictionary is empty.

Solution

First, we initialize our example dictionary with some data.
let a = [
      "name"        : "John",
      "surname"     : "Doe"
]
Now, let’s see...
if a.isEmpty {
      print("Our dictionary is empty :(")
} else {
      print("Of course it's not empty - we just created it!")
}

How It Works

To check if a dictionary is empty, we can use its isEmpty property.
Of course it's not empty - we just created it!

9.3 Check if key exists in dictionary

Problem

I want to check if a specific key exists in a given dictionary.

Solution

First, we initialize our example dictionary.
var d = [
      "name"       :     "John",
      "surname"    :    "Doe",
      "email"      :     "[email protected]"
]
Now, let’s see...
if d["address"] != nil {
      print("Yes, address found!")
} else {
      print("Ooops, no address found!")
}

How It Works

To check if a given dictionary contains a specific key, we may use the dictionary’s subscript.
Ooops, no address found!

9.4 Check if object is dictionary

Problem

I want to check if a given object is of type dictionary.

Solution

First, we initialize our example “object” – let’s make it a dictionary, as expected.
var a : Any = [
      "name"       :    "John",
      "surname"    :    "Doe"
]
Now, let’s see...
if a is [String:String] {
      print("Yes, it's a String:String dictionary. Well done!")
} else {
      print("Oh, no, this is not a dictionary!")
}

How It Works

To check if an object is of type dictionary, we can use an X is a dictionary or X is [type:type] statement.
Yes, it's a String:String dictionary. Well done!

9.5 Check if two dictionaries are equal

Problem

I want to check if two different dictionaries are equal.

Solution

First, we initialize our dictionaries.
let a = ["name": "John", "surname": "Doe"]
let b = ["name": "Jane", "surname": "Doe"]
Let’s see...
if a == b {
      print("Yep, the dictionaries are equal")
} else {
      print("Nope, they are different dictionaries")
}

How It Works

To compare two dictionaries and check if they are equal, we can use the == comparison operator.
Nope, they are different dictionaries

9.6 Convert dictionary to array of tuples

Problem

I want to convert a given dictionary to an array of key-value tuples.

Solution

First, we initialize an example dictionary.
let fruit = [
      "banana"     : "yellow",
      "apple"      : "red",
      "watermelon" : "green"
]
Let’s map it to an array of tuples.
let fruitArray = fruit.map { ($0,$1) }
And... print the result.
print("Fruit: (fruitArray)")

How It Works

If we have a dictionary, we can convert it into an array, by mapping its key-value pairs to tuples using the dictionary’s map method .
Fruit: [("watermelon", "green"), ("apple", "red"), ("banana", "yellow")]

9.7 Convert dictionary to JSON string

Problem

I want to convert a dictionary object to its corresponding JSON string representation.

Solution

import Foundation
First, let’s create an example dictionary.
let dict : [String:Any] = [
      "name"       : "John",
      "surname"    : "Doe",
      "age"        : 69
]
do {
      // Convert our dictionary to Json data
      let json = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
      // Convert our Json data to string
      let str = String(data: json, encoding: .utf8)
      // And if all went well, print it out
      print(str ?? "Ooops... Error converting Json to string!")
}
catch let error
{
      print("Error: (error)")
}

How It Works

In order to convert a Swift dictionary to JSON, we may use the JSONSerialization class.
{
  "name" : "John",
  "surname" : "Doe",
  "age" : 69
}

9.8 Convert JSON string to dictionary

Problem

I want to convert an object represented as a JSON string to a dictionary object.

Solution

import Foundation
First, let’s set some test JSON.
let json = "{"name": "John", "surname": "Doe", "age": 69 }"
Then, we convert it to a Data object.
if let data = json.data(using: .utf8) {
      // if everything went fine,
      // it's time to convert our Data object to a Dictionary
      let result = try? JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
      // And finally, what about printing out our dictionary?
      print(result ?? "Ooops... Error converting Json!")
}

How It Works

In order to convert a JSON string to a Swift dictionary, we may use the JSONSerialization class.
["name": John, "surname": Doe, "age": 69]

9.9 Create a dictionary with literal

Problem

I want to create a dictionary object from a dictionary literal.

Solution

This is a dictionary, with its type automatically inferred.
let a = [
      "Country"    : "Spain",
      "Capital"    : "Madrid"
]
This is the same one, but this time let’s set a type, for example, keys of String type, with values of String type.
let b : [String:String] = [
      "Country"    : "Spain",
      "Capital"    : "Madrid"
]

Let’s create a mixed dictionary with different types of elements. And different types of keys. This is rather tricky.

This time we have to explicitly say it’s of type [AnyHashable:Any]. Otherwise, the compiler will complain.
let c : [AnyHashable:Any] = [
      1         : "one",
      "two"     : 2
]
Let’s see what we’ve managed...
print("a: (a)")
print("b: (b)")
print("c: (c)")

How It Works

Creating a dictionary from a dictionary literal is as simple as listing your key-value pairs (with a : between the two), separated by commas, surrounded by a pair of square brackets.
a: ["Capital": "Madrid", "Country": "Spain"]
b: ["Capital": "Madrid", "Country": "Spain"]
c: [AnyHashable(1): "one", AnyHashable("two"): 2]

9.10 Create an empty dictionary

Problem

I want to create an empty dictionary object .

Solution

First approach: Use the [:] empty dictionary expression.
let a : [String:String] = [:]
Second approach: Use a dictionary constructor.
let b = [String:Any]()
Third approach: “Enforce” its type with as.
let c = [:] as [String:Int]
Let’s print our three... empty dictionaries.
print("a: (a), b: (b), c: (c)")

How It Works

In order to create an empty dictionary, it works pretty much as with the arrays ; the only thing you have to specify is the type of items (keys and values) it’s going to contain.
a: [:], b: [:], c: [:]

9.11 Create NSDictionary from dictionary

Problem

I want to create an NSDictionary object from a dictionary.

Solution

import Foundation
First, we initialize our example array with some values.
let dict = [
      "name"      : "John",
      "surname"   : "Doe",
      "email"     : "[email protected]"
]
Let’s convert it to an NSDictionary.
let b = NSDictionary(dictionary: dict)
Let’s try using the NSDictionary’s hash property (not available for Swift pure dictionaries) to make sure we made it.
print("Final dictionary's hash: (b.hash)")
print("Yep, it's an NSDictionary!")

How It Works

In order to convert/bridge a dictionary to an NSDictionary, for example, when you need to access APIs that expect data in an NSDictionary instance, we can use the NSDictionary(dictionary:) initializer.
Final dictionary's hash: 3
Yep, it's an NSDictionary!

9.12 Get array of keys in dictionary

Problem

I want to get a given dictionary’s keys as an array.

Solution

Let’s initialize our test dictionary.
let dict = [
      "name"      : "John",
      "surname"   : "Doe",
      "email"     : "[email protected]"
]
Then, we get its keys into an array.
let keys = Array(dict.keys)
Let’s print the result...
print("Our dictionary keys: (keys)")

How It Works

A dictionary is a collection of key-value pairs. But what if we want to get just the keys? For that, we can use the dictionary’s keys property.
Our dictionary keys: ["name", "surname", "email"]

9.13 Get dictionary value for key

Problem

I want to get the value of a specific key from a given dictionary.

Solution

Let’s initialize our test dictionary.
let user = [
      "name"        : "John",
      "surname"     : "Doe",
      "email"       : "[email protected]"
]

Then, we get the user’s name.

Careful: This is optional; and it is not guaranteed that we’ll find this particular key in the dictionary.
if let userName = user["name"] {
      // Let's print the result
      print("Our user's name is: (userName)")
}

How It Works

A dictionary is a collection of key-value pairs. In order to retrieve a specific value, we may use the subscript along with the value’s key.
Our user's name is: John

9.14 Get size of dictionary

Problem

I want to get the size of a given dictionary.

Solution

First, we initialize our example dictionary with some date.
let a = [
      "name"       : "John",
      "surname"    : "Doe",
      "email"      : "[email protected]"
]
Now, let’s count how many key-value pairs we’ve got...
print("The dictionary contains (a.count) elements")

How It Works

To check the size of a dictionary, we can use its count property.
The dictionary contains 3 elements

9.15 Loop through a Dictionary

Problem

I want to loop through a dictionary, keeping track of each key-value pair.

Solution

Let’s initialize our example dictionary.
let userInfo = [
      "name"      : "John",
      "surname"   : "Doe",
      "email"     : "[email protected]"
]
Let’s iterate through our dictionary...
for (item,value) in userInfo {
      print("(item) = (value)")
}

How It Works

Looping through a dictionary is just as easy as looping through an array. Only we have to keep track of both parts of each pair: key and value.
name = John
surname = Doe

9.16 Merge two dictionaries

Problem

I want to merge two different dictionaries into a new one.

Solution

First, we initialize our example dictionaries.

Note

The dictionary that is going to change must be declared as a variable (in this case, dictB will be merged into dictA).

var dictA = [ "1" : "one", "2" : "two", "4" : "four" ]
let dictB = [ "1" : "uno", "3" : "tres" ]
Let’s loop through our dictB.
for (key,value) in dictB {
      // if key doesn't exist, create it
      // if it does exist, update it
      dictA[key] = value
}
Now, let’s print our new dictionary...
print("Merged: (dictA)")

How It Works

If we have two dictionaries and want to merge them, that is: to add one dictionary’s items to another one, updating keys if necessary; there is no built-in method, but we can loop and update the keys/values accordingly.
Merged: ["3": "tres", "2": "two", "1": "uno", "4": "four"]

9.17 Read contents of Plist from file into dictionary

Problem

I want to read the contents of a Property List (Plist) file into a dictionary object.

For example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
      <key>Books</key>
      <array>
            <dict>
                  <key>author</key>
                  <string>Fyodor Dostoyevsky</string>
                  <key>title</key>
                  <string>Crime and Punishment</string>
            </dict>
            <dict>
                  <key>author</key>
                  <string>George Orwell</string>
                  <key>title</key>
                  <string>Animal Farm</string>
            </dict>
      </array>
</dict>
</plist>

Solution

import Foundation
Now, let’s set our Plist path.
let path = "tests/test.plist"
And read our Plist.
if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
      var format = PropertyListSerialization.PropertyListFormat.xml
      let dict = try? PropertyListSerialization.propertyList(from: data, options: [], format: &format) as! [String : String]
      // Finally, we print out the result
      print(dict ?? "Error converting Plist")
}

How It Works

In order to read a property list (XML Plist) string as a dictionary, we may use PropertyListSerialization’s propertyList method .

9.18 Read contents of Plist from string into dictionary

Problem

I want to read the contents of a Property List (Plist) string into a dictionary object.

Solution

import Foundation
First, we initialize our Plist string.
let plist = "<?xml version="1.0" encoding="UTF-8"?>" +
"<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">" +
"<plist version="1.0">" +
      "<dict>" +
            "<key>one</key>" +
            "<string>value</string>" +
            "<key>two</key>" +
            "<string>another value</string>" +
      "</dict>" +
"</plist>"
Now, let’s read it.
let data = plist.data(using: .utf8)
var format = PropertyListSerialization.PropertyListFormat.xml
let dict = try? PropertyListSerialization.propertyList(from: data!, options: [], format: &format) as! [String : String]
And print out the result...
print(dict ?? "Error converting plist")

How It Works

In order to read a property list (XML Plist) string as a dictionary, we may use PropertyListSerialization’s propertyList method .
["one": "value", "two": "another value"]

9.19 Remove all items from dictionary

Problem

I want to remove all elements from a given dictionary.

Solution

First, we initialize a test dictionary.
var user = [
      "name"      : "John",
      "surname"   : "Doe",
      "email"     : "[email protected]"
]
Then, we remove all of its contents.
user.removeAll()
Let’s see our new - empty – dictionary...
print("User: (user)")

How It Works

To remove all values from an existing dictionary (basically: empty it), we may use the dictionary’s removeAll method.
User: [:]

9.20 Remove dictionary item by key

Problem

I want to remove a specific item from a given dictionary, by its key.

Solution

First, we initialize a test dictionary.
var user = [
      "name"       : "John",
      "surname"    : "Doe",
      "email"      : "[email protected]"
]
Then we delete its name or, literally, remove its values with a name key.
user.removeValue(forKey: "name")
Let’s see the resulting dictionary...
print("User: (user)")

How It Works

To remove a particular key-value pair from an existing dictionary, we may use the dictionary’s removeValue(forKey:) method .
User: ["surname": "Doe", "email": "[email protected]"]

9.21 Set dictionary value by key

Problem

I want to set the value of a specific key in a given dictionary.

Solution

Let’s initialize our test dictionary.
var user = [
      "name"      : "John",
      "surname"   : "Doe",
      "email"     : "[email protected]"
]
What about changing the user’s name?
user["name"] = "Jane"
And print the result...
print("User: (user)")

How It Works

A dictionary is a collection of key-value pairs. In order to set a specific value, we may use the subscript along with the value’s key and assign the new value.
User: ["name": "Jane", "surname": "Doe", "email": "[email protected]"]

9.22 Summary

In this chapter, we learned how we can make use of one of the most powerful constructs in Swift: the dictionary.

In the next chapter, we’ll be looking into more advanced Swift topics: from working with numbers and dates, to interacting with the file system, performing web requests, or even launching system processes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.77.208