How to Use Arrays in Swift 3.0

Screenshot 2014-08-14 05.36.46The most important collection type is arguably the array. Arrays in Swift are simple to understand, but have a quite rich set of uses with a few new constraints compared to their Objective-C counterparts.

For those unfamiliar with arrays, arrays are an ordered collection of data.  Think of an array like a railroad train and each piece of data is a railroad car.  We refer to a specific railroad car by how many railroad cars from the front of the train a specific car is. The third car for example my be a dining car. We write this as car[third] where car is the identifier of the array and third is the index.  An index is always a positive integer, and arrays in every language I can think of start with zero. That means our index is usually one less than what we expect. If we used numbers for the index, we would write car[2] for the third car.

Swift arrays come in two flavors: dynamic and static. Static arrays keep their size and contents completely: after initialization no changes happen. The code cannot change the elements or the size of the array. Unlike Objective-C ‘s NSArray, which can change the value of an element, static arrays are completely static. Like any constant, static arrays use memory far more efficiently than dynamic.  Dynamic arrays allow us to change the size and contents of the array, similar to NSMutableArray in Objective-C.

Trying the Examples

For those who want to try the examples, you can open a Playground. Name it SwiftArrays. For those who don’t like playgrounds, you can also create a new single view application. In the ViewController class, you can add this code to the viewDidLoad method. Build and run to see the results. In both cases, results will be in the console. Open up the bottom pane of Xcode to see your results. I will sometimes add a print function to show the results, but not in all cases. If you wish to see a specific result, use print.

Declaring Array in Swift

Compared to Objective-C, Swift arrays are not as picky.  Swift accepts any type, not just classes in an array. Declaring static and dynamic arrays is the difference between let and var. The let declaration gives us a static array and the var a dynamic array. In both cases we set the initial values of the array in the declaration:

let myStaticArray = [
     "apple",
     "pear",
     "banana",
     "raspberry"
]
var myDynamicArray = [1,2,3,5,7,13,17,23]

Literal arrays are not limited to one physical line. Like myStaticArray, for readability you can use a separate line for each element of the array. This helps with readability of code. In the examples above, implicit typing can deduce that the static array is a string array and the dynamic is an integer array. We can declare an array of a given type by placing the element’s type in square brackets. An integer dynamic array would look like this:

var myExplicitDynamicArray:[Int] = [1,2,3,5,7,13,17,23]

If we want a empty integer dynamic array, we would declare it like this:

var myEmptyDynamicArray:[Int] = []

or this shorter form:

var myOtherEmptyArray = [Int]()

If you need an array of a certain size with the same data in each element, there is a special initializer for it:

var myVanillaArray = Array(repeating: "Vanilla", count: 5)

This creates an array ["Vanilla","Vanilla","Vanilla","Vanilla","Vanilla"]

Accessing Elements in Swift

To access an element of an array, use the identifier of the array with a subscript enclosed in square brackets. The first element of the array is element 0. For example

// access first element
print(myStaticArray[0])

//fourth element
print(myDynamicArray[3])

//add fifth element(7)
//to sixth element(13)
print(myDynamicArray[4] + myDynamicArray[5])

If you try to access an element outside of the array, you will get a run-time error. If you had this in your code:

print(myStaticArray[10])

You would get the following error when you ran the app:
fatal error: Array index out of range
The index can never be negative. Any negative value such as

print(myStaticArray[-1])

is also out of range and will give an error.

We do know the range of the array due to the count property, which gives us the number of elements in the array.

print(myStaticArray.count)

Since arrays start at zero, our last element is one less than the count. To access the last element of an array you could write:

print(myStaticArray[myStaticArray.count - 1])

We can get our last element of the array this way

let lastElement = myStaticArray.count - 1
print("\(myStaticArray.count) elements in array")
print("last  element is \(myStaticArray[lastElement])")

We can also get the last element using the last property.

print("last element is also \(myStaticArray.last)")

The last property returns an optional, so you will need to unwrap it.

Iterating Array Data in Swift

If you need to access all elements of an array we can use loops. The best for sequential access is the
for..in loop

var myArray=[1,2,3,5,7,11,13,17]
var total = 0
for element in myArray {
    print("\(element) ")
    total += element
}
print(" =  \(total)")

In line 3, the for loop, starting at the first element of the loop, sequentially gets each value for the array. This works well if you just need the value. Sometimes you need the index of the array, since the code needs multiple indexes. A variation For..in uses ranges of the index.

total = 0
for index in 1..<myArray.count{
    //add an element and the previous element together
    let sum = myArray[index] + myArray[index-1]
    total += sum
}
print(" =  \(total)")

Note two things I did here in line 3. I did not write myArray.count-1. Swift has two range operators. One ... is a full range. Had I used that, the correct code is 1...myArray.count-1 . Swift has the ..< operator. This goes one less than the top of the range. Since we use ranges to describe arrays so often, 1..<myArray.count is cleaner and more understandable code than 1...myArray.count-1.

Secondly, I started at 1 and not 0. Line four adds the current and the previous array elements together. If I started at 0, I’d get an out of bounds error. Starting at 1 avoids that.

Some cases might have two arrays which share a common index and the same number of elements. Since arrays must have elements of the same type, this situation shows up when you have two arrays of different types you need to associate with each other in a one to one relationship. I might have these two arrays of type String and Int respectively:

var iceCreamFlavors=["Vanilla","Chocolate","Strawberry"]
var iceCreamLeft=[20,5,50]

Then I would use a for loop with an index, from 0 to the count for one of the arrays:

for index in 0..<iceCreamFlavors.count{
    print("We have \(iceCreamLeft[index]) units of \(iceCreamFlavors[index]) left")
}

this produces the result:

We have 20 units of Vanilla left
We have 5 units of Chocolate left
We have 50 units of Strawberry left

The for loops get every case, since they increment index by one. If you want some increment other than one, you need a while loop:

// Sum every other element using a while loop
total = 0
var index = 0
while index < myArray.count {
    print("\(index), \(myArray[index])")
    total += myArray[index] 
    index += 2
}
print(" =  \(total)")

When I want to work backwards starting at the last element and going to the first element, we also use a while loop:

//same as the for loop, but counting backwards
total = 0
index = myArray.count - 1
while index >= 0 {
    print("\(index), \(myArray[index])")
    total += myArray[index]
    index -= 1
}
print(" =  \(total)")

Adding and Removing Elements

To add an element to the end of the array, use the .append() method or the += operator. These two statements do the same:

    myArray = [1,2,3,5,7,11,13,17]
    myArray.append(23)
    myArray += [29]

The array [1,2,3,5,7,11,13,17] appends two numbers, changing to:  [1,2,3,5,7,11,13,17,23,29]
The advantage to the += operator is you can append another array if the elements are of the same type in both arrays.

myArray += [31, 37]

results in [1,2,3,5,7,11,13,17,23,29,31,37] In Swift, operators keep a consistency across type, which might make some traditional programmers a bit squeamish. The += in their mind is an arithmetic operator, but it works for many types, including arrays. Swift continues such consistency with merging two arrays with the + operator

var myStringArray = ["apple","pear","banana","raspberry"]
var myOtherStringArray = ["Pepperoni","Sausage"]
var jointArray = myStringArray + myOtherStringArray

This code results in jointArray being ["apple","pear","banana","raspberry","Pepperoni","Sausage"]

To insert an element at a particular position, use the insert:at: method, remembering that the first index is zero:

myArray.insert(2,at:2)

This results in [1,2,2,3,5,7,11,13,17,23,29,31,37]

To change an element, assign a value to the specific element, like this:

myStringArray = ["apple","banana","raspberry","mango"]
myStringArray[1] = "blackberry"

Will change myStringArray to ["apple","blackberry","raspberry","mango"]. You can change a range of values if both arrays are the same type.

myStringArray[1...2] = ["beagle bone","arduino"]

Will change  ["apple","blackberry","raspberry","mango"] to ["apple","beagle bone","arduino","raspberry","mango"] . Range values specify the range to replace. You can replace with fewer items

myStringArray[1...3] = ["blackBerry", "kit kat"]

Changes elements 1,2,3 to only two elements making the array ["apple","beagle bone","arduino","raspberry","mango"] to ["apple","blackBerry", "kit kat","mango"]

To delete an element, there are two methods, removeAtIndex() and removeLast(). To remove the last element in the array

myStringArray.removeLast()

Changes the array ["apple","blackBerry", "kit kat","mango"] to ["apple", "blackBerry","kit kat"]
If we wanted to delete blackberry which is an index of 1, we would use remove(at:):

myStringArray.remove(at:1)

Changes the array to ["Apple","kit kat"]

When passing arrays in parameters we use the same syntax as declaring them:

func listArray(array:[Int]){
    for element in array{
        print(element)
    }
}

I could then call this function with

listArray(myArray)

Arrays Are for Classes and Types

Arrays can take any class. A common class to place into an array is a custom class for your model. For example , you might have a class to keep track of cookies

//Using arrays in a class
class Cookie{
    var name = ""
    var price = 0.00
    var rating = 0
    init(){}
    init(name:String,price:Double,rating:Int){
        self.name = name
        self.price = price
        self.rating = rating
    }
}

In your view controller, you would define an array to hold your all your cookies:

var cookie = [Cookie]()
cookie +=  [Cookie(name: "Chocolate Chip", price: 0.25, rating: 10)]
cookie += [Cookie(name: "Oatmeal", price: 0.20, rating: 5)]
cookie += [Cookie(name: "Peanut Butter", price: 0.20, rating: 4)]
cookie += [Cookie(name: "White Chocolate Macadamia", price: 0.50, rating: 10)]
cookie +=  [Cookie(name: "Butter Ganache", price: 0.35, rating: 9)]
cookie +=  [Cookie(name: "Chcocolate Cream", price: 0.22, rating: 7)]

Several methods in view controllers such as UITableViewController and UIPickerView access the array. For example in a picker view we could have this:

//example function -- see UIPickerView references for more detail
func pickerView(pickerView: UIPickerView,
    titleForRow row: Int,
    forComponent component: Int) -> String?{
        return cookie[row].name
}

Optionals and Array

Arrays can be used with optionals. Very often we may set an array to be optional to check for an empty state.

var optionalArray :[String]! = nil

We can also make our elements nil

var optionalElements : [String?] = [nil,"2","3","4",nil,"6"]

Working with Objective-C Arrays in Swift

There are several differences between in Objective-C and Swift. If you need a Objective-C NSArray because you have an API that uses it, you can always declare your array as:

var myImmutableArray:NSArray! = ["x","y","2"]

Remember that NSArrays  can be nil, so  it ‘s a good idea to make it an optional like I did above. I find Objective-C arrays clunky, and will tend to avoid them if I can. Many of the API’s will bridge Swift and Objective-C without issues so there is little need to do this, but there may be a few places where they don’t. You will need to declare an NSArray, when an array has elements of multiple classes.

Arrays are a rich, often used data structure. I thought this might help some of them. Hope it did.

The Whole Code

The code below is a playground. Open a playground in Xcode or the playgrounds app and cut and paste this code in. You can also use an IBM sandbox version of this code on the web by clicking the link.

//: Playground - noun: a place where people can play

import UIKit

//: Swift Arrays -- A demonstration of Arrays
//: In Swift 3.0
//:(c)2016 Steven Lipton
//: lesson text can be found at [http://wp.me/p2kbUU-7g0] (http://wp.me/p2kbUU-7g0)

//Declaring Arrays

//Literal static array
let myStaticArray = [
    "apple",
    "pear",
    "banana",
    "raspberry"
]

//literal Dynamic Array
var myDynamicArray = [1,2,3,5,7,13,17,23]

//Empty Dynamic Arrays
//Both of these work
var myEmptyDynamicArray:[Int] = []
var myOtherEmptyArray = [Int]()

//An array with the same values in all
//elements
var myVanillaArray = Array(repeating: "Vanilla", count: 5)

// access first element
print(myStaticArray[0])

//fourth element
print(myDynamicArray[3])

//add fifth element(7)
//to sixth element(13)
print(myDynamicArray[4] + myDynamicArray[5])

//uncomment to produce runtime
// out of bounds error
//comment out  to run code.
//myDynamicArray[10]

//using count
print(myStaticArray.count)

//finding the last element with .count
let lastElement = myStaticArray.count - 1
print("\(myStaticArray.count) elements in array")
print("last  element is \(myStaticArray[lastElement])")

//last property, note it is optional
print("last element is also \(myStaticArray.last)")

//for..in loop
var myArray=[1,2,3,5,7,11,13,17]
var total = 0
for element in myArray {
    print("\(element) ")
    total += element
}
print(" =  \(total)")


//for loop with range
total = 0
for index in 1..<myArray.count{
    //add an element and the previous element together
    let sum = myArray[index] + myArray[index-1]
    total += sum
}
print(" =  \(total)")

// Using a common index for two arrays
// often used when you have different types in the two arrays
var iceCreamFlavors=["Vanilla","Chocolate","Strawberry"]
var iceCreamLeft=[20,5,50]
for index in 0..<iceCreamFlavors.count{
    print("We have \(iceCreamLeft[index]) units of \(iceCreamFlavors[index]) left")
    }


// Sum every other element using a while loop
total = 0
var index = 0
while index < myArray.count { print("\(index), \(myArray[index])") total += myArray[index] index += 2 } print(" = \(total)") //same as the for loop, but counting backwards total = 0 index = myArray.count - 1 while index >= 0 {
    print("\(index), \(myArray[index])")
    total += myArray[index]
    index -= 1
}
print(" =  \(total)")

//add an element either way
myArray.append(23)
myArray += [29]

//add two elements to an array
myArray += [31, 37]


//concatenation of arrays
var myStringArray = ["apple","pear","banana","raspberry","mango"]
var myOtherStringArray = ["Pepperoni","Sausage"]
var jointArray = myStringArray + myOtherStringArray

//insertion
myArray.insert(2,at:2)

//modifying elements
myStringArray[1] = "blackberry"
print(myStringArray)

//modifying more than one element 1:1
myStringArray[1...2] = ["beagle bone","arduino"]
print(myStringArray)

//modfying more than one element,
// but changing less than the number of elements
myStringArray[1...3] = ["blackBerry", "kit kat"]
print(myStringArray)

//delete last element of the array
myStringArray.removeLast()
print(myStringArray)

//delete selected element in the array
myStringArray.remove(at:1)
print(myStringArray)


//making a function with an array as a parameter
func listArray(_ array:[Int]){
    for element in array{
        print(element)
    }
}
listArray(myArray)

//Using arrays in a class
class Cookie{
    var name = ""
    var price = 0.00
    var rating = 0
    init(){}
    init(name:String,price:Double,rating:Int){
        self.name = name
        self.price = price
        self.rating = rating
    }
}
// create array from a class
var cookie = [Cookie]()
cookie +=  [Cookie(name: "Chocolate Chip", price: 0.25, rating: 10)]
cookie += [Cookie(name: "Oatmeal", price: 0.20, rating: 5)]
cookie += [Cookie(name: "Peanut Butter", price: 0.20, rating: 4)]
cookie += [Cookie(name: "White Chocolate Macadamia", price: 0.50, rating: 10)]
cookie +=  [Cookie(name: "Butter Ganache", price: 0.35, rating: 9)]
cookie +=  [Cookie(name: "Chcocolate Cream", price: 0.22, rating: 7)]

//example function -- see UIPickerView references for more detail
/* Non functional example
 func pickerView(pickerView: UIPickerView,
 titleForRow row: Int,
 forComponent component: Int) -> String?{
 return cookie[row].name
 }
 */

//Arrays and optionals
//optional array
var optionalArray :[String]! = nil
//optional Array elements
var optionalElements : [String?] = [nil,"2","3","4",nil,"6"]

//arrays for use with Objective-C code
var myImmutableArray:NSArray! = ["x","y","2"]
print(myImmutableArray)



3 Replies to “How to Use Arrays in Swift 3.0”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s