Arrays - FUNDAMENTALS - Understanding Swift Programming: Swift 2 (2015)

Understanding Swift Programming: Swift 2 (2015)

PART 1: FUNDAMENTALS

5. Arrays

An array in Swift is an ordered list of values. Arrays in Swift are declared to have values only of a specific type, and all values must be of that type or you will get a compiler error. This is part of the emphasis on type safety in Swift.

However, note that “the same type” has a liberal interpretation, given subtyping. See the discussion on subtyping in the section on Polymorphism in Chapter 11 on “Object-Oriented Programming” and the discussion in Chapter 30 on “Type Checking and Type Casting”.

Examples of arrays are:

var birds = ["Cardinal", "Steller's Jay", "Finch"]

var temperatures = [100.3, 88.3, 299.2]

In the case of the birds array, the values are inferred to be of type String, while in the case of the temperatures array, the values are inferred to be of type Double.

Arrays can be variables, like those above, or constants:

let marineMammals = ["Sea Lions", "Sea Otters", "Humpback Whales", "Spotted Dolphins"]

If an array is specified as a constant, it cannot be modified. Elements cannot be added to it, replaced, or deleted. An array specified as a variable can have elements added to the end of it, inserted in the array at any point, replaced, or deleted from the array.

Constant and variable arrays in Swift are basically replacements for the Objective-C classes NSArray and NSMutableArray. The values of NSArray cannot be changed once set (that is, they are immutable), while the values of NSMutableArray can be changed.

Because of the requirement that in Swift arrays must be all of the same type, arrays in Swift are easier to use than their Objective-C counterparts but are less flexible. Objective-C arrays can accept any object, but it must be a true object, not a fundamental type like an integer or floating point number. Fundamental types must be converted to an object like NSNumber before being placed in an array, and converted back when retrieved.

The type of an array consists of the type of the values in it surrounded by brackets. The following arrays have their type explicitly declared:

var birds: [String] = ["Cardinal", "Steller's Jay", "Finch"]

var temperatures: [Float] = [100.3, 88.3, 299.2]

The type is defined as [String] or [Float]. This means an array consisting of values with the type String or Float.

The declaration and the assignment can be separate statements:

var cities: [String]

cities = ["San Jose", "Ventura", "San Luis Obispo"]

Note, however, that to declare a variable or constant without initializing it, you must do it explicitly with a type annotation.

An empty array can be created as follows:

var cities = [String]()

var cities: [String] = []

var numbers = [Int]()

var numbers: [Int] = []

There are two ways of accessing arrays: using subscripts, or using the methods associated with arrays. We will demonstrate access with subscripts first, and then with the methods associated with arrays.

Accessing Arrays Using Subscripts

Subscripts are commonly used as an easy way to access values in an array.

We can use a subscript to retrieve a value:

var cities = ["San Jose", "Ventura", "San Luis Obispo"]

var nameOfCity = cities[1]

print (nameOfCity) // Prints: Ventura

(The first item in a Swift array has an index of 0, as in most languages.)

Subscripts can be used to change an array in any way allowed, including appending a value to the end of the array (if indirectly), replacing one or more values of an array, inserting one or more values into an array at a given location, deleting a value from an array, and even deleting all of the values of an array.

Thus, the following will change the value of the second item in the array from "Ventura" to "San Diego":

cities = ["San Jose", "Ventura", "San Luis Obispo"]

cities[1] = "San Diego"

The result is:

["San Jose", "San Diego", "San Luis Obispo"]

Note, however, that we cannot use a subscript to refer to an item in an array that does not exist, or we will get a compiler or runtime error:

cities = ["San Jose", "Ventura", "San Luis Obispo"]

cities[3] = "San Diego" // Compiler Error

We can also replace multiple values at the same time. This makes use of the range syntax discussed in an earlier chapter. Thus, the following will replace both "San Diego" and "San Luis Obispo":

cities = ["San Jose", "San Diego", "San Luis Obispo"]

cities[1...2] = ["Mendocino", "Humboldt"]

The numbers in the range refer to the subscript indices in the existing array. This says "replace the values in locations 1 to 2 with the following elements".

The result is:

["San Jose", "Mendocino", "Humboldt"]

We can do this even if the number of values we are adding is different from the number of values that we are specifying in the subscripts, allowing us to effectively insert additional values to or delete values from the array:

cities = ["San Jose", "San Diego", "San Luis Obispo"]

cities[2...2] = ["Mendocino", "Humboldt", "Redding"]

This yields the following:

["San Jose", "San Diego", "Mendocino", "Humboldt", "Redding"]

Note that this replaces the last element in the array. We cannot use subscripts directly to append an item to the end of the array because we cannot use a subscript that points to beyond the boundaries of the existing array.

We can add a new value to the end of the array, however, with the append method:

cities = ["San Jose", "San Diego", "San Luis Obispo"]

cities.append ("Sierra Madre")

The array will now be:

["San Jose", "San Diego", "San Luis Obispo", "Sierra Madre"]

And note that arrays can hold multiple copies of the same value. If we do the same append operation again, we will get two "Sierra Madre" values:

cities.append("Sierra Madre")

The array will now be:

["San Jose", "San Diego", "San Luis Obispo", "Sierra Madre", "Sierra Madre"]

Accessing Arrays Using Methods

We have already seen that we can add elements to the end of an array with the append method:

cities = ["San Jose", "San Diego", "San Luis Obispo"]

cities.append ("Sierra Madre")

The removeAtIndex method will remove a particular element:

cities = ["San Jose", "San Diego", "San Luis Obispo"]

cities.removeAtIndex(2)

will result in the array:

["San Jose", "San Diego"]

The method insertAtIndex:

cities = ["San Jose", "San Diego"]

cities.insert("Monterey", atIndex:1)

will result in the array:

["San Jose","Monterey", "San Diego"]

The method removeAll:

cities = ["San Jose", "San Diego", "Monterey"]

cities.removeAll()

will result in the empty array:

[]

The method removeLast:

cities = ["San Jose", "San Diego", "Monterey"]

cities.removeLast()

will result in the array:

["San Jose", "San Diego"]

The Reference Manuals for the classes NSArray and NSMutableArray contain potentially useful methods that can be used to operate on Swift arrays. The NSArray class contains methods for operations that are read-only, while the NSMutableArray class contains methods for operations that change the values in the array.

Note that if you want to use APIs like NSArray and NSMutableArray in Playground, you have to import either the Foundation framework or the UIKit framework (which includes Foundation).

Additional Array Capabilities

We can use the "+" or addition operator to add two arrays together:

let cities = ["San Jose", "San Diego"]

let cities2 = ["San Luis Obispo", "San Francisco"]

let cities3 = cities + cities2

print(cities3)

// Prints: ["San Jose","San Diego", "San Luis Obispo", "San Francisco"]

Two useful properties are associated with arrays. The count property will tell you the size of the array:

print("The cities array has \(cities.count) cities in it")

The isEmpty property (a Boolean) will tell you whether the array has no elements (has a count of 0):

if(cities.isEmpty) {

print("The cities array has no values in it")

}

else {

print("The cities array has at least one value")

}

You can also iterate over an array:

let cities = ["San Jose", "San Diego", "San Luis Obispo", "San Francisco"]

for city in cities {

print(city)

}

The details of the for-in syntax has been explained in the chapter on the flow of control. This is just a for loop that goes through every item in the array, from beginning to end, setting the variable city each time to the value in the array.

Arrays are value types. (They are implemented as structures). That means that if you make a copy of an array, and change an element in it, it will not change the original. Thus:

cities = ["San Jose","San Diego", "San Luis Obispo"]

var cities2 = cities

cities2[0] = "Monterey"

print (cities) // Prints: ["San Jose", "San Diego", "San Luis Obispo"]

print (cities2) // Prints: "["Monterey", "San Diego", "San Luis Obispo"]

Zipping Together Two Arrays

A capability that was added in Swift 1.2 for arrays is the zip method. This allows you, given two arrays, to “zip them together” to create a single array of tuples. Each tuple has an element from the first array in the first position, and an element from the second array in the second position.

For example:

let array1 = [1, 2, 3]

let array2 = ["one", "two", "three"]

let zippedArray = zip(array1, array2)

The above code will produce the following array:

[(1, "one"), (2, "two"), (3, "three")]

This can be seen most easily with:

print (Array (zippedArray))

(At present zipped arrays do not seem to be accessible via subscripts.)

Note that there is a potential problem when the two arrays are not exactly the same length. If this happens, elements at the end of the longer array will be discarded as necessary.

Hands-On Exercises

Go to the following web address with a Macintosh or Windows PC to do the Hands-On Exercises.

For Chapter 5 exercises, go to

understandingswiftprogramming.com/5