Packaging Data in Collections

With numeric types and strings, one thing we’ll frequently want to do is to put them into collections. Nearly all languages have multiple ways of putting items into groups so we can then organize and perform operations on the entire group. Swift provides three main types of collections: arrays, sets, and dictionaries.

To start playing with these, start a new playground called CollectionsPlayground, and delete the line that creates the "Hello, playground!" string.

Arrays

For many of us, the most frequently used collection is the array. Arrays contain multiple items and maintain the ordering of those items. They also allow for the same item to appear multiple times in the array.

We’ll start with an array of strings that lists our favorite iPhone models. Declare an array as follows, and immediately check its dynamicType:

 var​ models = [​"iPhone SE"​, ​"iPhone 6s"​, ​"iPhone 7"​]
 type(of:models)

We can create an array by just putting its contents, comma-separated, inside square brackets. We can see from the results pane that this evaluates to these three strings, and the type(of:) is inferred to be Array<String>, meaning an Array of Strings.

Now let’s add an item at the front of the array:

 models.insert(​"iPhone 7 Plus"​, at: 0)

Our array now has four strings. Keep in mind, however, that we can add only Strings because that’s the type of the array. If we wanted to be able to add other types, like any of the numeric types, we would have had to originally declare that models accepts any Swift type, which we would write as var models : Array<Any>. There’s also a simpler syntax for array type declarations: [Any].

As our array grows, it likely won’t fit on one line of the results pane. Fortunately, there’s a way to see the whole thing. Mouse over the last line in the results pane, and two icons will appear on the far right: Quick Look and Show Result.

images/startingswift/results-quick-look-preview-buttons.png

Click the rightmost button, Show Result, to see the results shown directly below the line of code that produced them.

images/startingswift/results-preview-in-source.png

The Quick Look button tries to do a similar presentation in a popover window rather than presenting the results in our source pane. In this case, the array members are too wide to fit in the popover, and have to be scrolled vertically as well, so it’s not that useful this time.

Let’s dig into our array. To access a member of an array by its index, we can use the square-brace syntax familiar from C, Java, and many other languages:

 let​ firstItem = models[0]

The evaluation pane shows that firstItem has been set to the value "iPhone 7 Plus", which we inserted a few lines back.

Since we can insert, we can, of course, remove items as well, either with removeAtIndex or removeLast. To see the shortened array in the results pane, we type models by itself on the next line.

 models.removeLast()
 models

Keep in mind that all of these mutating operations are possible only because models was originally declared with the var keyword. If we’d used let, Swift would infer we wanted the array to be constant and would have created an immutable array.

Swift arrays have a few other neat tricks that make it easy to combine and split arrays, provided their types are compatible. Try this:

1: let​ iPhones = [​"iPhone SE"​, ​"iPhone 6s"​, ​"iPhone 7"​, ​"iPhone 7 Plus"​]
2: let​ iPads = [​"iPad Air 2"​, ​"iPad Pro"​, ​"iPad mini"​]
3: models = iPhones
4: models.append(contentsOf: iPads)
5: models.insert(contentsOf: [​"iPod touch"​], at: 4)

In this section of code, lines 1 and 2 create immutable arrays called iPhones and iPads, respectively. Line 3 assigns our models array to now be the contents of iPhones. Then, on line 4, we use the appendContentsOf function to append the contents of the iPads array to the models array. If we don’t want to add items at the end, we can use the insertContentsOf function to insert an array at a given index. On line 5, we insert a one-element array of iPod touch models at index 4, putting it between the iPhones and iPads. As we can see in the evaluation pane, our array now has eight items.

Sets

Arrays are a bread-and-butter collection, but for certain tasks, sets make more sense. A set has no sense of order and does not allow duplicate items. Sets are useful for when you want to simply know whether or not a given item is part of a collection, and you don’t care if it’s “before” or “after” other members of the collection.

Let’s kick off an empty set and start adding stuff to it.

1: var​ set = ​Set​<​String​>()
2: set​.insert(​"iPhone 7"​)
3: set​.insert(​"iPhone 7"​)
4: set

Line 1 shows the recipe for creating an empty collection of any type. We have to declare the type (because there are no objects to infer it from), so we use the type Set<String>, and empty parentheses to call the initializer for that type.

On line 2 we add the string "iPhone 7", and on line 3 we do it again. Then we just evaluate set on line 4 to see what’s in it.

Look at the results on the last line: the set still only has one member. That’s because a given item can appear only once in a Set; we don’t care how many of something are in the set, just whether that thing is in or out. This is also reflected in the return value of each insert: we get back a Bool indicating whether or not the insert succeeded, and an object that is either the newly inserted object, or an equivalent object already in the set that caused the new insert to be rejected.

Where sets really shine is their operators for determining membership between members of multiple sets. Let’s create two sets to play with:

 var​ iPhoneSet : ​Set​ = [​"iPhone 7"​]
 var​ iPadSet : ​Set​ = [​"iPad Air 2"​, ​"iPad mini"​, ​"iPad Pro"​]

Notice that as a convenience, we can create a Set from an Array. In this example, ["iPhone 7"] is one array, and ["iPad Air 2", "iPad mini", "iPad Pro"] is another. We have to declare the Set type (because otherwise the square-brace syntax would imply an Array), but at least the type of the Set’s contents (Strings) can be inferred.

If we were interested in what members are in both sets, that’s a one-line call:

 iPhoneSet.intersection(iPadSet)

The results pane shows us an empty set—Set([])—because no items are members of both sets. Let’s change that. The iPhone 7 Plus feels nearly as big as an iPad mini, so let’s add it to both sets and try another call to intersect.

 iPadSet.insert(​"iPhone 7 Plus"​)
 iPhoneSet.insert(​"iPhone 7 Plus"​)
 iPhoneSet.intersection(iPadSet)

Now the results pane shows us the one item in both sets, "iPhone 7 Plus".

If you studied set theory in high school, you’ll recall that an intersection is the items that are in both sets, and that the union is all the members of both sets. Swift gives that to us, too:

 iPhoneSet.union(iPadSet)

This gives us everything from both sets (you might have to use the Quick Look or Show Results buttons to see them all). Notice that "iPhone 7 Plus" appears only once, despite being present in both sets. After all, the return type is a Set, and any object can appear only once in a set.

Dictionaries

Swift’s third major collection type is dictionaries. A dictionary is a collection that maps keys to values, which gives you a way to quickly look up a given value in the future, provided you have the corresponding key.

Let’s create a dictionary that lets us look up iOS device sizes by model name:

 let​ sizeInMm = [
 "iPhone 7"​: 138.1,
 "iPhone 7 Plus"​ : 158.1,
 "iPad Air 2"​ : 240.0,
 "iPad Pro"​ : 305.7]
 type(of:sizeInMm)

As we can see in the results pane, this creates a dictionary with four key-value pairs, and the type of this collection is inferred to be Dictionary<String, Double>, meaning the keys are Strings and the values are Doubles.

To access a value, we put the key in square braces, like this:

 sizeInMm[​"iPhone 7"​]
 sizeInMm[​"iPad mini"​]

The results pane shows that we got back 138.1 for the "iPhone 7" key and nil for the "iPad mini" key, which makes sense because sizeInMm doesn’t have that key.

Dictionaries are good for fast lookups of single items, although it’s also possible to walk through the whole collection. To do that, though, we’re going to need ways to have our code loop through the collection. So let’s move on to that.

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

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