Swift Array

ARRAY

An array is an ordered collection of values of the same type.

let footballers = [“Rooney”, “Kanu”, “Neymar”, “Xavi”]

The variable footballer is a collection of names of football players. An array of string values. Using the keyword “let” means the array is a constant (immutable) and will never change as opposed to variables(mutable) which is declared with the keyword “var”

var footballers = [“Rooney”, “Kanu”, “Neymar”, “Xavi”] footballers = [“Dog”, “Cat”]

This is ok. and we can still go further and return the original values, since cats and dogs are not footballers.

footballers = [“Rooney”, “Kanu”, “Neymar”, “Xavi”]

But the code below would throw an error:

let footballers = [“Rooney”, “Kanu”, “Neymar”, “Xavi”] footballers = [“Dog”, “Cat”]

An array must not necessarily have a value when it is being declared. We can declare empty array in swift this way

var footballersJerseyNumber = [ ]

The compile will throw an error: Empty collection literal requires an explicit type
This means the compiler isn’t able to infer the type from the declaration. It can’t tell if this is an array of integers or strings, etc.

To fix this, we use a type annotation to make the type explicit.

var footballersJerseyNumber:[Int] = [ ]

Element in an array are zero-indexed. This means in the array footballers, Rooney has an index of 0, Kanu has index 1, Neymar has an index of 2, and so on.

Properties and Method of swift Array.
isEmpty: this is a boolean value that is used to check whether an array is empty. It return true if empty, false if array is not empty.

if footballers.isEmpty {  
   print("Yes it is: \(footballers.isEmpty)")
}else {
    print("Definitely not: \(footballers.isEmpty)")
}

if footballersJerseyNumbers.isEmpty {  
    print("Yes it is: \(footballersJerseyNumbers.isEmpty)")
}else {
    print("Definitely not: \(footballersJerseyNumbers.isEmpty)")
}

count: an integer that tells the number of elements in the array. It return zero if the array is empty.

print(footballers.count)// ---> 4  
print(footballersJerseyNumbers.count)// ---> 0  

Notice the count for footballers is 4. The index of the last element (Xavi) is 3. Index of last element in an array is one less than the count because array is zero-indexed

if footballers.count < 11 {  
    print("we need more players")
}else {
    print("we have our first eleven")
}

Notice we can also use count to tell if an array is empty.

if footballersJerseyNumbers.count == 0 {  
    print("Yes it is: \(footballersJerseyNumbers.isEmpty)")
}else {
    print("Definitely not: \(footballersJerseyNumbers.isEmpty)")
}

first: This returns the first element of the array. If the array is empty, the value of this property is nil.

print(footballers.first) // ---> Optional("Rooney")  
print(footballersJerseyNumbers.first) // ---> nil

first property returns an optional (swift solution for absence of value. This is because there is no guarantee that an array must have value. It could be empty.

We have to unwrap the optional to get the value at the first index

if let firstPlayer = footballers.first {  
    print(firstPlayer)
}else {
    print("Array is empty: \(footballers.first)")
}
// ---> Rooney

if let firstPlayerJerseyNumber = footballersJerseyNumbers.first {  
    print(firstPlayerJerseyNumber)
}else {
    print("Array is empty: \(footballersJerseyNumbers.first)")
}
// ---> Array is empty: nil

last: This returns the last element of the collection. If the array is empty, the value of this property is nil.

print(footballers.last) // ---> Optional("Xavi")  
print(footballersJerseyNumbers.last) // ---> nil

if let lastPlayer = footballers.last {  
    print(lastPlayer)
}else {
    print("Array is empty: \(footballers.last)")
}
// ---> Xavi

if let lastPlayerJerseyNumber = footballersJerseyNumbers.last {  
    print(lastPlayerJerseyNumber)
}else {
    print("Array is empty: \(footballersJerseyNumbers.last)")
}
// ---> Array is empty: nil

The first property is just an elegant way of accessing first element of an array. We can access element of an array using the index of the array.
Since “Rooney” is at index zero, we can get the value “Rooney” by doing this:

footballers[0] // —> Rooney  
print(footballers.first == footballers[0]) //—> true  

Same goes for property last.

let numberOfPlayers = footballers.count

print(footballers[numberOfPlayers-1])//—>Xavi

print(footballers.last == footballers[numberOfPlayers-1]) //—>true  

This way of accessing elements in an array is called subscripting. We can use this to access every element of the array especially elements between first and last, since there is no inbuilt elegant way to do that

Let’s try something like this:

print(footballers[8])

we get an error saying: fatal error: Index out of range

if this happens in a app, the app will crash. The array footballers has a count of 4, therefore the last element in it will have an index 3. Index 8 is out of the range of the array. If it ever happens we need to access an element in a particular index known, we can check first if the index is not out of range.

if footballers.count > 8 {  
    print(footballers[8])
}else {
    print("8 out of range")
}

To get every element in an array, we can iterate through the array.

for names in footballers {  
    print(names)
}
/* Rooney
    Kanu
    Neymar
    Xavi
*/

We can also access array using range. Lets say we want a sub-array containing the first three footballers. We can do this

let top3Footballer = footballers[0...2]  
print(top3Footballer) //["Rooney", "Kanu", "Neymar"]  

Get the two middle players:

let middlePlayers = footballers[1...2]  
print(middlePlayers) //["Kanu", "Neymar”]  

Or even do something as irrelevant as this

let onePlayer = footballers[1...1]  
print(onePlayer) //["Kanu”]  

Any value can be used as index in the range as long as the value is within the bounds of the array and the first element is less than the second. If the first element is greater than the second, we get the error:Can't form Range with upperBound < lowerBound.

We can also use subscripting to modify an element in an array.

print(footballers[3]) //Xavi  
footballers[3] = "Henry"  
print(footballers[3]) //Henry  

We can only do this with mutable array. We declared top3Footballer as a constant. Let’s try modifying an element in it.

top3Footballer[0] = "Silva" //Cannot assign subscript:'top3Footballer' is a constant

Error is shown, and the compiler will give the option of changing the ‘let’ to ‘var’.

We can use range to modify element within the range we specify

footballers[0...2] = ["Kane", "Pele", "Johnson"]  
print(footballers) //["Kane", "Pele", "Johnson", "Henry"]  

Try this:

footballers[0...2] = ["Pogba"]  
print(footballers) //["Pogba", "Henry”]  
print(footballers.count) // 2  

The first element is replaced with “Pogba”, the second and third element is removed and our array now have a count of 2

This quite different from this:

footballers[0...1] = ["Ronaldo", ""]  
print(footballers) // ["Ronaldo", “”]  
print(footballers.count) //2  

Here the second element is replaced with empty string and the count of the array remains the same.

min(): this method returns the minimum element in the sequence.

let playerPositions = [9, 11, 3, 4, 5, 8, 10, 1, 7, 2, 6]  
print(playerPositions.min()) //Optional(1)  

max(): this method returns the maximum element in the sequence

print(playerPositions.max()) //Optional(11)

contain(): this is an array method that takes an element (string, int, or any type as long as it is the type of the array), and returns true if the element is in the array. Returns false if the array does not contain the element.

print(footballers.contains("Pogba”)) //flase  
print(playerPositions.contains(4)) //true  

We can also check if the element exist in specific range of an array
print(playerPositions[2...7].contains(6)) //false

append(_ newElement: Element): this method takes an element and add the element to the end of a mutable array

footballers.append("Drogba")  
print(footballers) //["Ronaldo", "", "Drogba"]  

We can append an element to an array using the += operator. The syntax is as shown below"

array += [newElement]

footballers += ["messi", "myself"]  
print(footballers) // ["Ronaldo", "", "Drogba", "messi", "myself"]  

insert(_ newElement: Element, at i: Int): Inserts a new element at the specified position. The new element is inserted before the element currently at the specified index. The element at the specified index and every other element after, will have their index increased by 1.

footballers.insert("nani", at: 1)  
print(footballers) //["Ronaldo", "nani", "", "Drogba", "messi", "myself”]  
print(footballers.count) //6  

The new element “nani” did not replace the original element in that index.

remove(at index: Int): Removes and returns the element at the specified position.

let element = footballers.remove(at: footballers.endIndex-1)  
print(footballers) //["Ronaldo", "nani", "", "Drogba", "messi"]  
print(element) //myself  

removeLast(): Removes and returns the last element of the array.

print(last) //messi  
print(footballers) //["Ronaldo", "nani", "", "Drogba”]  

removeFirst(): Remove and returns the first element of the array

sort():sorts and return the sorted elements of the array in ascending order.

let sortedPositions = playerPositions.sorted()  
print(sortedPositions) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]  
print(playerPositions) //[9, 11, 3, 4, 5, 8, 10, 1, 7, 2, 6]  

Note the original array is not modified.

Of course we can sort the array in place too

print(playerPositions.sorted()) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

We can also decide how we want the sorting to be done. Let’s say we want the sorting in descending order. We can do this:

let descendingArray = playerPositions.sorted { (a:Int, b:Int) -> Bool in  
    a > b
}
print(descendingArray) // [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]  

enumerated(): According to apple: “Returns a sequence of pairs (n, x), where n represents a consecutive integer starting at zero, and x represents an element of the sequence.”

for (index, name) in footballers.enumerated() {  
    print(index, name)
}
/*
 0 nani
 1
 2 Drogba
 */

filter: this function loops through the array, takes each element, evaluate the function in the closure. If the evaluated function returns true, the element is included into the resulting array. if the function returns false, the element will not be included in the resulting array.

We can use filter to get array of even positions

let evenPositions = playerPositions.filter({$0 % 2 == 0})  
print(evenPositions) //[4, 8, 10, 2, 6]  

Here, each element is evaluated to see if it’s remainder when divided by 2 is 0. If it is, the element is added to the resulting array.

Another example : get array of positions less than 7.

let lessThanSevenPositions = playerPositions.filter({$0 < 7 })  
print(lessThanSevenPositions) //[3, 4, 5, 1, 2, 6]  

Reduce: this reduces an array to one value by taking an initial value, with a function that manipulates the initial value and the element in each iteration. Lets get the sum of all elements in playerPosition array.

let sumOfPositions = playerPositions.reduce(0) { return $0 + $1}  
print(sumOfPositions) //66  

Another example on array of string.

let stringArray = ["reduce", "In", "Action"]  
let result = stringArray.reduce("") { return $0 + $1 }  
print(result) //reduceInAction  

Map: this is simply iterating over an array and perform some operations on each element. let get an array containing the double of each element in playerPosition array.

let doubleEachPosition = playerPositions.map({$0*2})  
print(doubleEachPosition) // [18, 22, 6, 8, 10, 16, 20, 2, 14, 4, 12]  

filter, map and reduced combined

let finalResult = playerPositions.map({$0 + 5}).filter({$0 % 2 != 0}).reduce(0) { $0 + $1 }  
print(finalResult) //55  

We have covered a lot about array in swift. But this is, in no way exhaustive. Here is a gist containing most of the code.