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!
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:
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) |
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
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?
Swift’s Array
type has two handy methods that answer these questions:
- The
isEmpty
method returnstrue
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, ifisEmpty
returnstrue
), 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:
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:
- An array consisting of only the parents (elements 0 and 1).
- 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
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:
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
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:
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
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:
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
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:
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:
…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:
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:
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
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:
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:
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:
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:
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.