Lesson 7 - 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
.
(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. String
s
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 String
s - 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 following exercise, Solved tasks for Swift lesson 7, we're gonna practice our knowledge from previous lessons.
Download
By downloading the following file, you agree to the license termsDownloaded 439x (103.82 kB)