Lesson 7 - Arrays in Swift

Swift Basic constructs Arrays in Swift

In the previous lesson, Type system: Optionals in Swift, we learned how to use Optionals. In today's Swift tutorial, we're going to introduce you all to the array data structure and show you what it's capable of accomplishing.

Array

Imagine that you want to store some information about multiple items, e.g. you want to keep 10 numbers in memory, each of the fields of a checkerboard or names of 50 users. Perhaps you realize that there must be an easier way than to start typing variables like user1, user2 ... up until user50. Despite the fact that there may be 1000 of them. How would go about searching for something in there? Definitely not like that! :)

If we need to store a larger amount of variables of the same type, we can solve this problem using an array. We can imagine it as a row of boxes, each of them containing one item. The boxes are numbered by indexes, the first one has index 0.

Array structure in Swift

(We see an array of 8 numbers in this picture)

Programming languages are very different in the way they work with arrays. In some languages (especially the older ones, compiled), it wasn't possible to create an array with a size specified at runtime (e.g. to specify its size using some variable). Arrays had to be declared with a constant size in the source code. A workaround was made by inventing pointers and custom data structures, which often lead to errors in manual memory management and to program instability (e.g. in C++). On the other hand, some interpreted languages allow us to not only declare arrays of any size but to also change the size of an existing array (it's possible e.g. in PHP). Swift deals with arrays in a relatively modern way. You don't have to worry about the array size (you don't even have to specify it) and we'll use a method to add array items so no worries about indexes as well. This collection type (container structure) is often called a list instead of an array in other languages. However, Swift calls it array. We use loops for the mass handling of array items.

We declare an array using brackets and parentheses:

var numbers = [Int]()

numbers is obviously a name of our variable.

We access array items via brackets but only if the item already exists. That can be confusing if you're migrating from another language. First, we'll add a few items using the append() method to which we can pass a number (Int which will be stored at the beginning of the array) or even another array of the same type (in our case, Int).

var array = [Int]()
array.append(34)

Filling arrays manually like this wouldn't be too effective. Let's use a loop and fill an array with numbers from 1 to 10. We'll use a for loop to do just that:

var numbers = [Int]()
for i in 1...10 {
        numbers.append(i)
}

If we want to print this array, we need to add this piece of code after the one above:

for number in numbers {
        print(number, terminator:" ")
}

Now we can see the true power of the for loop in Swift. Other languages have another foreach keyword, but all we have to do is to pass the array after the in keyword instead of a numeric range and the loop will go through all the array items.

1 2 3 4 5 6 7 8 9 10

Arrays provide the count property, in which the number of items is stored.

Of course, we can also fill an array manually, even without accessing each index gradually. We'll use curly brackets and separate items by commas:

let simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

Since we don't want anyone to change our array now, we declared it using let which makes the array constant. We omit the type specification since Swift easily recognizes that it's a String array from the items. Of course, we can specify it explicitly as well:

let simpsons: [String] = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

Arrays are often used to store intermediate results, which are used later in the program. When we need some result 10 times, we won't calculate the same thing 10 times, instead, we'll calculate it once and put it into an array, then we just read the result.

Array methods

Swift provides us with several helpful methods for working with arrays. Let's look at them.

sort() and sorted()

As the name suggests, the methods sort an array. The sort() method sorts an already existing arrays (it must be declared using var) and sorted() returns a new sorted array, so we mustn't forget to assign it to a variable. The methods are even so clever that they work according to what we have stored in the array. Strings are sorted alphabetically, numbers are sorted depending on their value. Let's try to sort and print our Simpsons family:

var simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsons.sort()
for simpson in simpsons {
        print(simpson)
}

The output:

Bart
Homer
Lisa
Maggie
Marge

And the same thing using sorted():

var simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

let simpsons_sorted = simpsons.sorted()
for simpson in simpsons_sorted {
        print(simpson)
}

The output:

Bart
Homer
Lisa
Maggie
Marge

Try making an array of numbers and sort them, so you'll understand that it works for numerical datatypes as well.

reverse and reversed()

These methods reverse an array (the first item will be the last, and so on). The principle is the same as with the sorting. The reverse() method sorts an existing array, reversed() returns a new reversed array. We can use reversing e.g. for descending sorting:

val simpsons: Array<String> = arrayOf("Homer", "Marge", "Bart", "Lisa", "Maggie")
simpsons.sort()
simpsons.reverse()
for simpson in simpsons {
        print(simpson)
}

The output:

Maggie
Marge
Lisa
Homer
Bart

index(of: )

Returns the index of a given array element. The method returns Optional(Int) since it may happen that the array element simply isn't there and it doesn't make much sense to return any value then. You should know Optionals from the previous lesson. In order to get the value safely, we're going to use the if let construct to assign the Simpson's index to a position variable, if such exists in our array. If it doesn't exist, the else branch will be executed.

let simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
print("Hello! Enter the name of a character in the Simpsons (you may only choose from the core family members): ")
let simpson = readLine()!
if let position = simpsons.index(of: simpson) {
        print("Yeah, that's my number \(position + 1) Simpson!")
} else {
        print("Hey! that's not Simpson!")
}

The output:

Hello! Enter the name of a character in the Simpsons (you may only choose from the core family members):
Homer
Yeah, that's my number 1 Simpson!

Copying arrays

Sometimes it may happen that you need an exact copy of your array. This is either very simple or quite complicated thing to do in Swift. It depends on whether your array contains value types (Int, Double, String) or reference types (class instances, which we'll discuss in the following Swift courses). In the first case, we just create a new array variable and assign the existing one to it. We'll use our Simpsons array, which consists of Strings - the value types and we'll make a copy of it.

var simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

var simpsonsCopy = simpsons

We won't bother with reference data types yet.

count

We've already mentioned count, it contains the array's length. It's not a method, but a property, so we don't use parentheses () here.

isEmpty

As you may guess, this property contains true if the array is empty. It's better than asking if the number of array items (count) equals zero. The code clearly says we're interested in the possibility the array is empty.

min() and max()

Math methods returning the lowest element (min()) and the greatest element (max()) of the array. The result is returned as an Optional since it may happen the array is empty.

first and last

Just by looking at the names of the methods, we can say they return the first and the last element.

contains()

The method returns true/false depending on whether an element given through the method parameter exists in the array.

Deleting elements

The modern array design in Swift allows us to delete elements easily.

remove(at: )

The remove() method removes an element at a given array index. However, we have to make sure that the index really exists, otherwise the program will crash. You may want to delete a specific element from the array more often than an element at a given index. Swift unfortunately doesn't offer a simple method to deal with this, but the index(of:) method, which we already know, surely helps:

if let bartIndex = simpsons.index(of: "Bart") {
        simpsonovi.remove(at: bartIndex)
}

This is how we can delete Bart from our Simpsons array. Note that the array must be declared as var, because a let constant won't allow us to modify it. The remove(at: ) method will also return the deleted element if you'd like to work with it further.  

removeAll()

There isn't much to explain here. The method simply removes all the elements from the array. There is also a variant with the keepingCapacity parameter. Arrays hold free capacity for the elements in the background and increases it if necessary. If you have a lot of elements in an array, you want to remove them but fill it with a similar number of different elements later, you can save Swift's effort and keep the array's capacity. But it's nothing important; you can use removeAll() without a parameter just as well.  

removeLast() and popLast()

Both methods remove the last element in the array and return it. So how are they different? Basically, they differs in cases when the array is empty. removeLast() would cause an error while popLast() would simply return an empty Optional. If you know the array won't be empty, it's easier to use removeLast() since you don't have to deal with an Optional.   These methods are also useful if you want to emulate the stack data structure using arrays since Swift doesn't offer it unlike other languages. It's simple. It works like an imaginary stack of paper on the table. New items (papers) always come on top and when we're removing, we'll first get to the top ones - the ones that were added last. Use the append() method to add items at the end of the array and the removeLast()/popLast() methods to simply achieve the stack behavior.

That's enough for today, you can play with arrays for a while if you'd like. In the next lesson, Strings in Swift - Working with single characters, I've got a surprise for you I think you might like ;-)


 

Download

Downloaded 3x (103.82 kB)

 

 

Article has been written for you by Filip Němeček
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
Thumbnail
All articles in this section
Swift basic constructs
Activities (4)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!