Categories
Swift Kick

Game of Phones, part 1 (or: Arrays in the Swift programming language) [Updated]

Update, July 24, 2014: I’ve updated this article to match the updates made to Swift with the release of Xcode beta 4. Gotta love languages in beta!

ios 8 is coming

swift kick

Welcome to another installment of Swift Kick, the series of articles on Global Nerdy covering programming in Apple’s new Swift programming language. Fell free to follow along and fire up your Xcode 6 beta, copy the examples, and experiment on your own! You can find earlier articles in this series by clicking on the Swift Kick logo to the right.

Spoiler alert! This article uses the events from the TV series Game of Thrones as a framework. You don’t need to have watched the series to understand this article, but it will reveal some plot points from the first three seasons.

Game of Thrones is popular among the sort of people who like programming, and given that the show often adds and (very brutally) deletes characters, I thought it would be a fun basis for an article on arrays in Swift.

Here are the Starks, the first family that we’re introduced to in the series:

starks

In this article, we’re going to be working with an array representing the Stark Family. As you might expect, it’s called starkFamily, and here’s its visual representation:

The Stark Family
Parents Children
0
Ned
(Dead)
1
Catelyn
(Dead)
2
Robb
(Dead)
3
Jon
(Alive)
4
Sansa
(Alive)
5
Arya
(Alive)
6
Bran
(Alive)
7
Rickon
(Alive)
Ned Catelyn Robb Jon Sansa Arya Bran Rickon

Here’s code to define the array and then display its contents:

var starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"]
println(starkFamily)

Here’s the output of that code:

[Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]

While most statements in Swift end at the end of a line, there are certain exceptions. One such exception is made for array literals, which you can write over several lines as shown below. I prefer defining longer arrays this way, as I find them easier to read:

var starkFamily = ["Ned",
                   "Catelyn",
                   "Robb",
                   "Jon",
                   "Sansa",
                   "Arya",
                   "Bran",
                   "Rickon"]

If you’ve programmed in Python or Ruby, you’re familiar with this sort of thing, where the interpreter (or in Swift’s case, the compiler) “knows” that arrays and dictionaries can extend beyond a single line.

Getting individual array elements

stark family array notation

If you’re familiar with programming languages like C#, Java, JavaScript, Lua, Objective-C (more modern versions, anyway), PHP, Python and Ruby, you’ll find Swift’s basic array notation familiar — it’s good ol’ reliable arrayName[index], where arrayName is the name of the array, and index is an integer specifying which element of the array we want to retrieve. As with most programming languages, the first element of an array with n elements is at index 0, the second is at index 1, the third is at index 2, and so on up until the last element, which is at index n-1.

In the code snippet below, we want to access the 3rd and 6th elements of the starkFamily array. Put another way, we want the starkFamily elements at indices 2 and 5:

println("The Stark family member at index 2 is \(starkFamily[2]).")
println("The Stark family member at index 5 is \(starkFamily[5]).")

Here’s the output of that code:

The Stark family member at index 2 is Robb.
The Stark family member at index 5 is Arya.

Setting individual array elements

The same array notation can be used to set array elements. In the code below, we want to change the contents of the element at index 0 from “Ned”, which is a nickname, to his proper name, “Eddard”:

starkFamily[0] = "Eddard"
println(starkFamily)

Here’s the output:

[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]

Is the array empty, and if not, how many elements are in the array?

empty fuel gauge

Swift’s Array type has two handy methods that answer these questions:

  • The isEmpty method returns true if the array has no elements, false otherwise
  • The count method returns the number of elements in the array. If the array is empty (that is, if isEmpty returns true), then count returns 0.

For the code snippet below:

println("The statement that starkFamily is empty is \(starkFamily.isEmpty).")
println("There are \(starkFamily.count) members in the Stark Family.")

the resulting output is:

The statement that starkFamily is empty is false.
There are 8 members in the Stark Family.

Getting ranges of array elements

Swift lets you get sub-arrays of an array by specifying a range of elements. This is one of those things that’s easier to show first, then tell afterwards, so I’ll let this picture do the talking first:

selecting sub-arrays using ranges

  • starkFamily[0..<3] (with 2 dots and a <, also known as the half-open range operator) specifies an array made of the elements of starkFamily starting at index 0, and up to but NOT including the element at index 3. If you’re mathematically inclined, you can think of 2 dots as defining a left-closed, right-open interval, which you write as [0, 3).
  • starkFamily[0...3] (with 3 dots, also known as the closed range operator) specifies an array made of the elements of starkFamily starting at index 0, and up to and including the element at index 3. If you’re mathematically inclined, you can think of 3 dots as defining a closed interval, which you’d write as [0, 3].

Here some code showing array ranges in action. Let’s say we want to pull a couple of arrays out of starkFamily:

  1. An array consisting of only the parents (elements 0 and 1).
  2. An array consisting of only the children (elements 2 and beyond).
println("The parents in the Stark Family are \(starkFamily[0...1]).")
println("The children in the Stark Family are \(starkFamily[2...7]).")

Here’s the output:

The parents in the Stark Family are [Eddard, Catelyn].
The children in the Stark Family are [Robb, Jon, Sansa, Arya, Bran, Rickon].

The half-open range operator is useful for when you want to retrieve a range of array elements starting at some given index, and going on for the rest of the array. You use it in conjunction with the count property, like so:

println("The children in the Stark Family are \(starkFamily[2..<starkFamily.count]).")

Remember, in an array of n elements, the index of the last item is n – 1. Of course, you can always get an equivalent result with a 3-dot range…

println("The children in the Stark Family are \(starkFamily[2...starkFamily.count - 1]).")

…but in my opinion, that makes things more complicated than they need to be.

Adding elements to an array

Adding to the end of an array, part 1: The append method

hodor

Let’s add some elements to the end of the array.

While Hodor doesn’t provide much in the way of conversation — the only thing he can say is his own name — he’s practically part of the Stark family. Let’s add him to the end of the starkFamily array with the append method. Here’s a representation of what that would look like:

add hodor

Here’s the code:

println("Once again, the Stark Family:\n\(starkFamily)")
println("Let's add Hodor!")
starkFamily.append("Hodor")
println(starkFamily)

and here’s the output:

Once again, the Stark Family:
[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
Let's add Hodor!
[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor]

Adding to the end of an array, part 2: Adding single elements with the += operator

osha

Later in the series, Osha the wildling is taken prisoner and agrees to work for the Starks as a nanny, so she too is practically part of the family. Let’s add her to the starkFamily array, but using the += operator instead. Here’s the visualization of that operation:

add osha

Here’s the code:

println("Once again, the Stark Family:\n\(starkFamily)")
println("We'll add Osha:")
starkFamily += "Osha"
println(starkFamily)

And here’s the output:

Once again, the Stark Family:
[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor]
We'll add Osha:
[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor, Osha]

Adding to the end of an array, part 3: Adding arrays with the += operator

stark direwolves

In the very first episode of Game of Thrones, the Starks come across a dead direwolf and several surviving pups. Each of the pups — eventually named Grey Wind, Lady, Numeria, Summer, Shaggydog, and Ghost — is taken by the Stark children as a pet, making them practically part of the family. Let’s put the direwolves’ names into an array, and then add that array to starkFamily. Here’s the visualization:

add direwolves

The corresponding code:

var starkPets = ["Grey Wind", "Lady", "Nymeria", "Summer", "Shaggydog", "Ghost"]
println("The Stark pets: \(starkPets)")
starkFamily += starkPets
println("The Stark family, with pets: \(starkFamily)")

And the output:

The Stark pets: [Grey Wind, Lady, Nymeria, Summer, Shaggydog, Ghost]
The Stark family, with pets: [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor, Osha, Grey Wind, Lady, Nymeria, Summer, Shaggydog, Ghost]

Inserting new elements at a specified position

theon

What if we want to add elements to the array, but somewhere other than the end?

After his father’s failed rebellion against the Starks, Theon became a hostage and ward of the Stark family, who raised him as one of their own. Let’s add him to the family, between the two elder brothers, Robb and Jon, using the insert method:

add theon

var starkFamily = ["Ned",
                   "Catelyn",
                   "Robb",
                   "Jon",
                   "Sansa",
                   "Arya",
                   "Bran",
                   "Rickon"]
println("Let's add Theon, between Robb (index 2) and Jon (index 3)")
starkFamily.insert("Theon", atIndex: 3)
println(starkFamily)

The output:

Let's add Theon, between Robb (index 2) and Jon (index 3)
[Eddard, Catelyn, Robb, Theon, Jon, Sansa, Arya, Bran, Rickon, Hodor]

Want to add an element at the beginning of an array? Just use the insert method to insert the new element at index 0.

Deleting elements from an array

Deleting elements from a specified position

The advice given to people new to Game of Thrones is to not get too attached to a character, because anyone — even a lead character — could die. This happened in season 1 when Ned was falsely accused and found guilty of treason:

beheading

…and then Catelyn and Robb (and a good chunk of the army of the North) were killed at the “Red Wedding”, which got this sort of reaction from viewers:

Let’s reflect these deaths by deleting them from the starkFamily array. Here’s the visualization:

killing off characters

Here’s the code:

println(starkFamily)
starkFamily = ["Ned",
               "Catelyn",
               "Robb",
               "Jon",
               "Sansa",
               "Arya",
               "Bran",
               "Rickon"]
println("The Stark Family before: \(starkFamily)")
starkFamily.removeAtIndex(2)
starkFamily.removeAtIndex(1)
starkFamily.removeAtIndex(0)
println("The Stark Family after: \(starkFamily)")

And here’s the output:

The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Stark Family after: [Jon, Sansa, Arya, Bran, Rickon]

There’s a reason I removed element 2, then element 1, then element 0 rather than starting with element 0 and worked my way up. I’m going to leave it to you to figure why I did it that way.

Deleting the last element of an array

Suppose we want to get rid of the last element in starkFamily. One way to do it is to use the count property of the array to get the array’s size, then subtract 1 from it to get the last index of the array. Then, you’d use the removeAtIndex method to remove that element. It’s done in a single line of code:

starkFamily.removeAtIndex(starkFamily.count - 1)

While it’s simple, there’s an even simpler way that doesn’t require you to calculate the last index of the array. It’s the removeLast method, and it removes the last element of the array. Here’s the visualization:

removelast

Here’s the code:

starkFamily = ["Ned",
  "Catelyn",
  "Robb",
  "Jon",
  "Sansa",
  "Arya",
  "Bran",
  "Rickon"]
println("The Stark Family before: \(starkFamily)")
starkFamily.removeLast()
println("The Stark Family after: \(starkFamily)")

The output:

The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Stark Family after: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran]

Replacing ranges of array elements

Replacing a range of array elements with an array of equal size

don and betty draper
Let’s cross over to another popular show that airs on Sunday nights: Mad Men. As ill-advised as many of the choices made by the heads of the Stark family were, chances are those choices might by much worse if they were made by Don and Betty Draper. Still, people who make good choices don’t make good drama, so let’s go ahead and replace Ned and Catelyn with Don and Sally.

We could perform the replacement element by element:

starkFamily[0] = "Don"
starkFamily[1] = "Betty"

But we can reduce this operation to a single line by specifying a range in our array, and assigning a replacement array:

replace range equal size

For this code:

starkFamily = ["Ned",
               "Catelyn",
               "Robb",
               "Jon",
               "Sansa",
               "Arya",
               "Bran",
               "Rickon"]
println("The Starks: \(starkFamily)")
starkFamily[0...1] = ["Don", "Betty"]
println("The Draper-Starks: \(starkFamily)")

We get this output:

The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Draper-Starks: [Don, Betty, Robb, Jon, Sansa, Arya, Bran, Rickon]

Replacing a range of array elements with a smaller array

In season 4 of Mad Men, Betty had divorced Don and his second bachelorhood is in full swing. Let’s represent this with an array containing only Don, and let’s use this array to replace the range in starkFamily containing Ned and Catelyn. Here’s a visualization of the result:

replace range smaller

Here’s the code:

starkFamily = ["Ned",
               "Catelyn",
               "Robb",
               "Jon",
               "Sansa",
               "Arya",
               "Bran",
               "Rickon"]
println("The Starks: \(starkFamily)")
starkFamily[0...1] = ["Don"]
println("The Draper-Starks: \(starkFamily)")

And here’s the output:

The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Draper-Starks: [Don, Robb, Jon, Sansa, Arya, Bran, Rickon]

Replacing a range of array elements with a larger array

Later in the Mad Men series, Don marries his second wife, Megan. Let’s treat Don, Betty, and Megan as an array of parents and use them to replace Ned and Catelyn in starkFamily. Here’s the visualization of that arrangement:

replace range larger

Here’s the code:

starkFamily = ["Ned",
               "Catelyn",
               "Robb",
               "Jon",
               "Sansa",
               "Arya",
               "Bran",
               "Rickon"]
println("The Starks: \(starkFamily)")
starkFamily[0...1] = ["Don", "Betty", "Megan"]
println("The Draper-Starks: \(starkFamily)")

And here’s the output:

The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Draper-Starks: [Don, Betty, Megan, Robb, Jon, Sansa, Arya, Bran, Rickon]

Replacing a range of array elements with an empty array

Earlier in this article, we represented the deaths of Ned, Catelyn, and Robb by deleting them from the starkFamily array one at a time. Since Ned’s, Catelyn’s, and Rob’s elements are all in a row in the range [0...2], we can delete them in a single action by replacing that range with an empty array. Here’s the visualization:

replace range empty

Here’s the code:

starkFamily = ["Ned",
               "Catelyn",
               "Robb",
               "Jon",
               "Sansa",
               "Arya",
               "Bran",
               "Rickon"]
println("The Stark Family before: \(starkFamily)")
starkFamily[0...2] = []
println("The Stark Family after: \(starkFamily)")

And here’s the output:

The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
The Stark Family after: [Jon, Sansa, Arya, Bran, Rickon]

Want to find out more about arrays in Swift?

There’s more in the Collections Types chapter of Apple’s The Swift Programming Language, and I’ll cover more in part 2 as well.

4 replies on “Game of Phones, part 1 (or: Arrays in the Swift programming language) [Updated]”

Amazing use of a popular shows’ characters to teach a programming construct. You must be one of the designers of “The Matrix”.

Comments are closed.