Swift Programming from Scratch
The Swift Sandbox is integrated, making the exercises interactive. Read more about the book here.
Chapter 6: Arrays
Introduction
Often when you’re dealing with data you don’t just have a fixed amount of elements. Take for example a program where you compute the average of multiple grades in a class:
var grade1 = 4
var grade2 = 3
var average = Double(grade1 + grade2) / 2.0
print("Average grade: \(average)")
What if we wanted the program to also work when we have 3 grades?
We’d have to change our program to work with 3 grades.
var grade1 = 4
var grade2 = 3
var grade3 = 5
var average = Double(grade1 + grade2 + grade3) / 3.0
print("Average grade: \(average)")
After doing this it will no longer work with 2 grades. What if we wanted our program to work with any number of grades between 1 grade and 10 grades.
It’s not practical to write a separate program for each case. We would like to have something like a list of grades. This list would contain any number of grades. This is where arrays come in.
What is an array?
An array is an ordered collection that stores multiple values of the same type. That means that an array of Int
can only store Int
values. And you can only insert Int
values in it.
Declaring Arrays
To declare an array you can use the square brackets syntax([Type]
).
var arrayOfInts: [Int]
You can initialize an array with an array literal. An array literal is a list of values, separated by commas, surrounded by a pair of square brackets:
[value
, value
, ...
]
var arrayOfInts: [Int] = [1, 2, 3]
var arrayOfStrings: [String] = ["We", "❤", "Swift"]
` Keep in mind that you can create empty arrays if you don’t write any values.
var emptyArray: [Int] = []
Getting values
To get all the values from an array you can use the for-in
syntax. This is called iterating through an array.
var listOfNumbers = [1, 2, 3, 10, 100] // an array of numbers
var listOfNames = ["Andrei", "Silviu", "Claudiu"] // an array of strings
for number in listOfNumbers {
print(number)
}
// 1
// 2
// 3
// 10
// 100
for name in listOfNames {
print("Hello " + name + "!")
}
// Hello Andrei!
// Hello Silviu!
// Hello Claudiu!
To get the number of elements in an array you can use the count
property.
var listOfNumbers = [1, 2, 3, 10, 100] // an array of numbers
print(listOfNumbers.count) // 5
You can access specific elements from an array using the subscript syntax. To do this pass the index of the value you want to retrieve within square brackets immediately after the name of the array. Also you can get a subsequence from the array if you pass a range instead of an index.
Element in an array are indexed from 0 to the number of elements minus one. So an array with 3 elements will have elements at index 0, 1 and 2.
var listOfNumbers = [1, 2, 3, 10, 100] // an array of numbers
listOfNumbers[0] // 1
listOfNumbers[1] // 2
listOfNumbers[2] // 3
listOfNumbers[3] // 10
listOfNumbers[4] // 100
//listOfNumbers[5]// this gives an error uncomment this line to see it
listOfNumbers[1...2] // [2, 3] this is a subsequence of the original array
Adding values
You can add elements to the end of an array using the append
method.
// create a empty array of integers
var numbers: [Int] = []
for i in 1...5 {
numbers.append(i)
print(numbers)
// [1]
// [1, 2]
// [1, 2, 3]
// [1, 2, 3, 4]
// [1, 2, 3, 4, 5]
}
print(numbers)
// [1, 2, 3, 4, 5]
To insert an item into the array at a specified index, call the array’s insert(at:)
method.
var numbers: [Int] = [1, 2, 3]
numbers.insert(0, at: 0) // numbers will be [0, 1, 2, 3]
numbers.insert(9, at: 1) // numbers will be [0, 9, 1, 2, 3]
You can also append another array using the +=
operator.
var numbers: [Int] = [1, 2, 3]
numbers += [4, 5, 6] // numbers will be [1, 2, 3, 4, 5, 6]
// or just one value
numbers += [7] // numbers will be [1, 2, 3, 4, 5, 6, 7]
Removing Values
To remove an item from a specific index call the remove(at:)
method.
var numbers: [Int] = [1, 2, 3]
numbers.remove(at: 0) // numbers will be [2, 3]
Changing values
To change a value use the assignment operator (=
) after the subscript syntax.
var numbers: [Int] = [1, 2, 3]
numbers[0] = 7 // numbers will be [7, 2, 3]
numbers[1] = 5 // numbers will be [7, 5, 3]
numbers[2] = 4 // numbers will be [7, 5, 4]
Or you could replace a subsequence of values using range subscripting.
var numbers: [Int] = [1, 2, 3, 4, 5, 6]
numbers[2...4] = [0, 0] // numbers will now be [1, 2, 0, 0, 6].
Keep in mind that you don’t need to replace a sequence with another sequence with the same number of elements. In the example above numbers had 6 elements and after the replacement of the subsequence 2...4
([3, 4, 5]
) it had 5.
Type Inference
Thanks to Swift’s type inference, you don’t have to declare the type of an array if you initialize it with something other than an empty array literal([]
).
// arrayOfNumbers will be of type [Int]
var arrayOfNumbers = [1, 2, 3]
// arrayOfStrings will be of type [String]
var arrayOfStrings = ["We", "❤", "Swift"]
// arrayOfBools will be of type [Bool]
var arrayOfBools = [true, false, true, true, false]
// this is the proper way of declaring a empty array of Int - [Int]
var emptyArrayOfInts: [Int] = []
// this will infer into [Int] because the right hand side of the
// assignment has a known type [Int]
var anotherEmptyArray = emptyArrayOfInts
Copy Behavior
Swift’s Array types are implemented as structures. This means that arrays are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.
var numbers = [1, 2, 3]
var otherNumbers = numbers // this will create a copy of numbers
// this will append 4 to otherNumbers but not to numbers
otherNumbers.append(4)
// numbers = [1, 2, 3]
// otherNumbers = [1, 2, 3, 4]
Mutability
If you create an array and assign it to a variable, the collection that is created will be mutable. This means that you can change (or mutate) the collection after it is created. Changes can be done by adding, removing, or changing items in the collection. Conversely, if you assign an array to a constant, that array is immutable, and its size and contents cannot be changed. In other words if you want to be able to change an array declare it using the var
keyword, and if you don’t want to be able to change it use the let
keyword.
var numbers = [1, 2, 3, 4, 5, 6]
numbers.append(7) // [1, 2, 3, 4, 5, 6, 7]
numbers.remove(at: 0) // [2, 3, 4, 5, 6, 7]
let strings = ["We", "❤", "Swift"]
// the next lines will not compile!
strings.append("!") // this will give an error because strings is immutable
strings.remove(at: 0) // this will give a similar error
6.1 Max
Print the maximum value from listOfNumbers
.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
Output:
100
Input:
var listOfNumbers = [10, 12, 33, 11, 1]
Output:
33
Assume that the first element of the array is also the largest.
var listOfNumbers = [1, 2, 3, 10, 100]
var maxVal = listOfNumbers[0]
for number in listOfNumbers {
if maxVal < number {
maxVal = number
}
}
print(maxVal)
6.2 Odd
Print all the odd numbers from listOfNumbers
.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
Output:
1
3
Input:
var listOfNumbers = [10, 12, 33, 11, 1]
Output:
33
11
1
var listOfNumbers = [1, 2, 3, 10, 100]
for number in listOfNumbers {
if number % 2 != 0 {
print(number)
}
}
6.3 Sum
Print the sum of all the numbers from listOfNumbers
.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
Output:
116
Input:
var listOfNumbers = [10, 12, 33, 11, 1]
Output:
67
Store the sum in a variable. Keep increasing it.
var listOfNumbers = [1, 2, 3, 10, 100]
var sum = 0
for number in listOfNumbers {
sum += number
}
print(sum)
6.4 Odd Index
Print all the numbers from listOfNumbers
that are located at odd indexes.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
Output:
2
10
Input:
var listOfNumbers = [1, 10, 12, 33, 11, 1]
Output:
10
33
1
Use a while loop and the index subscripts.
var listOfNumbers = [1, 2, 3, 10, 100]
var i = 1
while i < listOfNumbers.count {
print(listOfNumbers[i])
i += 2
}
// 2
// 10
var listOfNumbers = [1, 2, 3, 10, 100]
for var i = 1; i < listOfNumbers.count; i += 2 {
print(listOfNumbers[i])
}
6.5 Going back
Print the numbers from listOfNumbers
in reverse order on separate lines.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
Output:
100
10
3
2
1
Input:
var listOfNumbers = [12, 33, 11, 1]
Output:
1
11
33
22
Use a loop that counts from the last index down to the first one.
var listOfNumbers = [1, 2, 3, 10, 100, 2]
var i = listOfNumbers.count - 1
while i >= 0 {
print(listOfNumbers[i])
i -= 1
}
var listOfNumbers = [1, 2, 3, 10, 100, 2]
for i in 1...listOfNumbers.count {
print(listOfNumbers[listOfNumbers.count - i])
}
var listOfNumbers = [1, 2, 3, 10, 100, 2]
for var i = listOfNumbers.count - 1; i >= 0; --i {
print(listOfNumbers[i])
}
6.6 Reverse
Reverse the order of the elements in listOfNumbers
without creating any additional arrays.
Input:
var listOfNumbers = [1, 2, 3]
Expected value:
listOfNumbers = [3, 2, 1]
Input:
var listOfNumbers = [12, 33, 11, 1]
Expected value:
listOfNumbers = [1, 11, 33, 12]
Use 2 indices.
At each step advance with the indices one step closer to the middle of thearray
.
var listOfNumbers = [1, 2, 3, 10, 100]
var firstIndex = 0
var lastIndex = listOfNumbers.count - 1
while firstIndex < lastIndex {
// swap
var tmp = listOfNumbers[firstIndex]
listOfNumbers[firstIndex] = listOfNumbers[lastIndex]
listOfNumbers[lastIndex] = tmp
// go to next pair
firstIndex += 1
lastIndex -= 1
}
6.7 Sorting
Sort the values in listOfNumbers
in descending order.
var listOfNumbers = [1, 2, 3, 10, 100]
var nElements = listOfNumbers.count
for fixedIndex in 0..<nElements {
for i in fixedIndex+1..<nElements {
if listOfNumbers[fixedIndex] < listOfNumbers[i] {
var tmp = listOfNumbers[fixedIndex]
listOfNumbers[fixedIndex] = listOfNumbers[i]
listOfNumbers[i] = tmp
}
}
}
var listOfNumbers = [1, 2, 3, 10, 100]
var nElements = listOfNumbers.count
var didSwap = true
while didSwap {
didSwap = false
for i in 0..<nElements - 1 {
if listOfNumbers[i] < listOfNumbers[i+1] {
var tmp = listOfNumbers[i]
listOfNumbers[i] = listOfNumbers[i+1]
listOfNumbers[i+1] = tmp
didSwap = true
}
}
}
In real life people don’t implement sorting anymore, they just call it.
array.sort(by: <) // will sort the array in ascending order
array.sort(by: >) // will sort the array in descending order
// you can also use the sorted method to create a sorted copy
let sortedArray = array.sorted(by: <)
var listOfNumbers = [3, 2, 100, 10, 1]
listOfNumbers.sort(by: <)
print(listOfNumbers)
// [1, 2, 3, 10, 100]
listOfNumbers.sort(by: >)
print(listOfNumbers)
// [100, 10, 3, 2, 1]
So to solve the problem we would write:
var listOfNumbers = [3, 2, 100, 10, 1]
listOfNumbers.sort(by: <)
6.8 Search
Find out if x
appears in listOfNumbers
. Print yes
if true and no
otherwise.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var x = 3
Output:
yes
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var x = 5
Output:
no
First assume that the element does not appear in the array. Store that state in a boolean variable.
var listOfNumbers = [1, 2, 3, 10, 100]
var x = 10
var xAppears = false
for number in listOfNumbers {
if number == x {
xAppears = true
}
}
if xAppears {
print("yes")
} else {
print("no")
}
6.9 Intersection
Print all the elements from otherNumbers
that appear in listOfNumbers
. Don’t print anything if listOfNumbers
andotherNumbers
have no common elements.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var otherNumbers = [1, 2, 3, 4, 5, 6]
Output:
1
2
3
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var otherNumbers = [5, 2, 3, 10, 13]
Output:
2
3
10
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var otherNumbers = [5, 6]
Output:
Use an approach similar to the Search
problem for each element fromotherNumbers
.
var listOfNumbers = [1, 2, 3, 10, 100]
var otherNumbers = [1, 2, 3, 4, 5, 6]
for otherNumber in otherNumbers {
for number in listOfNumbers {
if number == otherNumber {
print(number)
break
}
}
}
6.10 Divisors
Print all the numbers from listOfNumbers
that are divisible by at least one number from divisors
.
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var divisors = [2, 5]
Output:
2
10
100
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var divisors = [5, 3]
Output:
3
10
100
Input:
var listOfNumbers = [1, 2, 3, 10, 100]
var divisors = [7, 9, 13]
Output:
Try solving the problem for the case when listOfNumbers
contains a single element.
var listOfNumbers = [1, 2, 3, 10, 100]
var divisors = [7, 5]
for number in listOfNumbers {
for divisor in divisors {
if number % divisor == 0 {
print(number)
break
}
}
}
6.11 Greatest divisor of all
Find and print the greatest common divisor of all the numbers in numbers
. A common divisor of a list of numbers is a number that divides all of them.
Input:
var numbers = [12, 36, 720, 18]
Output:
6
Input:
var numbers = [3, 12, 36, 18, 7]
Output:
1
Use an approach similar to the case with only 2 numbers.
var numbers = [12, 36, 720, 18]
// find the minimum value in numbers
var maxDiv = numbers[0]
for number in numbers {
if number < maxDiv {
maxDiv = number
}
}
var gcd = 1
// find the biggest number that divides all the numbers
for divisor in 1...maxDiv {
// we assume that divisor divides all numbers
var dividesAll = true
for number in numbers {
// if we find one that does not divide by divisor
if number % divisor != 0 {
// we remeber and stop searching
dividesAll = false
break
}
}
// if divisor divides all numbers then it's the biggest one so far
if dividesAll {
gcd = divisor
}
}
print(gcd)
6.12 Fibonacci
Generate the first N
numbers in the fibonacci sequence. Store them in an array named fibonacci
and print them one on each line.
Input:
var N = 6
Expected value:
fibonacci = [1, 1, 2, 3, 5, 8]
Input:
var N = 9
Expected value:
fibonacci = [1, 1, 2, 3, 5, 8, 13, 21, 34]
Use append to add the next numbers
var N = 30
var fibonacci = [1, 1]
// your code here
var N = 30
var fibonacci = [1, 1]
for i in 2...N - 1 {
fibonacci.append(fibonacci[i-1] + fibonacci[i-2])
}
for number in fibonacci {
print(number)
}
Create an array with ones and compute all the numbers
let N = 30
var fib = [Int](repeating: 1, count: N)
// your code here
let N = 30
var fib = [Int](repeating: 1, count: N)
for i in 2..<N {
fib[i] = fib[i-1] + fib[i-2]
}
for number in fib {
print(number)
}
6.13 Divisors
Given a number
find and store all it’s divisors in an array called divisors
, then print the divisors in ascending order on separate lines.
Input:
var number = 6
Expected value:
divisors = [1, 2, 3, 6]
Output:
1
2
3
6
Input:
var number = 30
Expected value:
divisors = [1, 2, 3, 5, 6, 10, 15, 30]
Output:
1
2
3
5
6
10
15
30
Any value between 1
and number
can be a divisor of number
.
var number = 60
var divisors: [Int] = []
for divisor in 1...number {
if number % divisor == 0 {
divisors.append(divisor)
}
}
for divisor in divisors {
print(divisor)
}
6.14 Digits
Find and store the digits of number
from left to right in an array digits
, and then print the digits on separate lines.
Input:
var number = 12345
Expected value:
digits = [1, 2, 3, 4, 5]
Output:
1
2
3
4
5
Input:
var number = 232121
Expected value:
digits = [2, 3, 2, 1, 2, 1]
Output:
2
3
2
1
2
1
Store the digits from right to left if you find it easier. The digits from left to right are the reversed array.
var number = 12345
var digits: [Int] = []
while number > 0 {
var digit = number % 10
digits = [digit] + digits
number /= 10 // 12345 -> 1234 -> 123 -> 12 -> 1
}
for digit in digits {
print(digit)
}
6.15 Unique
Create a list unique
with all the unique numbers from listOfNumbers
, and then print the numbers on separate lines.
Input:
var listOfNumbers = [1, 2, 3, 1, 2, 10, 100]
Expected value:
unique = [1, 2, 3, 10, 100]
Output:
1
2
3
10
100
Input:
var listOfNumbers = [2, 3, 1, 1, 1, 2, 2, 2, 10]
Expected value:
unique = [2, 3, 1, 10]
Output:
2
3
1
10
var listOfNumbers = [1, 2, 3, 1, 2, 10, 100]
var unique: [Int] = []
for number in listOfNumbers {
var numberIsNew = true
for otherNumber in unique {
if number == otherNumber {
numberIsNew = false
break
}
}
if numberIsNew {
unique.append(number)
}
}
for number in unique {
print(number)
}
Swift Programming from Scratch
Read more about the book here.
Feel free to ask any questions in the comments bellow.
Hi. It is wellknown, that “Andrei” and “Silviu” are part of the “We ❤︎ Swift” team! But who is “Claudiu”?
Claudiu is our intern :). We hired him to learn programming in Swift using the exercises from Swift programming from Scratch. We know programming for so long that it’s hard to imagine how would it be not to. He helped us understand a lot about what a non-programmer mind thinks when seeing some code or learning a new concept.
There is obviously an “printing” error in the solution to problem 5.6. Instead of ++lastIndex one should read –last index.
sorry: –lastIndex
funny mistake! of course minus minus lastIndex (lastIndex = lastIndex – 1)
6.6 Reverse can be accomplished with much less code:
for x in listOfNumbers {
listOfNumbers.append(listOfNumbers[0])
listOfNumbers.removeAtIndex(0)
}
Edit sorry I misread the question, please delete these two comments.
You inspired me to try something similar… and there you go
for i in 0..<listOfNumbers.count {
listOfNumbers.insert(listOfNumbers[listOfNumbers.count – 1], atIndex: i)
listOfNumbers.removeLast()
}
You can even replace « listOfNumbers[listOfNumbers.count – 1] » by « listOfNumbers.last! » for more clarity.
actually it can be done with a function listOfNumbers.reverse()
6.6 Alternate
var theCount = listOfNumbers.count
var index = 0
for x in listOfNumbers {
listOfNumbers.insert(listOfNumbers[theCount – 1], atIndex: index)
listOfNumbers.removeLast()
index += 1
}
// result is [100,10,3,2,1]
how do you access the last element of a string array?
var strings: [String] = [“Hello”, “there”]
let lastIndex = strings.count – 1
strings[lastIndex] // there
// or
strings.last // Optional(“there”)
6.8 Search
Using reduce with a flag instead of a loop
var listOfNumbers = [1, 2, 3, 10, 100]
var x = 10
let xAppears = listOfNumbers.reduce(false) {flag, num in flag || num==x}
println(xAppears ? “yes” : “no”)
Hello,
How do I iterate through an array and convert each value to a string?
Thank you
Hi, you can use string interpolation to create a string out of any element of an array.
for value in array {
let stringValue = “\(value)”
}
Why do we need the break in Q6.9 and what does it do exactly?
break stops a loop.
for i in 1…3 {
print(i)
break
}
print(“go!”)
will print 1 go! not 1 2 3 go!
I need to check an array of random integers (between 1 and 9) and see if any combination of them will add up to 10. Is there an equation for that calculation?
for example, if the array was [8, 7, 6] it would return false
if the array was [5, 6, 4, 2, 9] it would return true.
The amount of Ints the array would vary.
You are looking for the Knapsack Algorithm – https://en.wikipedia.org/wiki/Knapsack_problem
in 6.15 -> why cant i run this code properly?
for number in 0..<unique.count {
for i in 1..<unique.count {
if unique[number] == unique[i] { // xcode alerts me with the bad instructions in this line?
unique.removeAtIndex(i)
}
}
}
because you mutated the array while iterating over it. The first for loop will go from 0 to the nr of elements from unique-1. That will crash your code after at least one number is removed because the last.
Looks like you think like a sculptor not a painter – you remove instead of adding. Here is a version of you solution that works:
var listOfNumbers = [1, 2, 3, 1, 2, 10, 100]
var unique: [Int] = listOfNumbers
var foundTwoOfTheSame = true
while foundTwoOfTheSame {
foundTwoOfTheSame = false
for number in 0..
It stops the for loops every time they remove a number - it does that until all the numbers are unique.
Hi guys!
Great site…..what does this mean?
if number % 2 != 0 {
Cheers!
You can find the answer in the first chapter under basic operators weheartswift.com/variables-constants-basic-operations/
if number is NOT divisible by 2
Recommend sets for interception:
var listOfNumbers: Set = [1, 2, 3, 10, 100]
var otherNumbers: Set = [1, 2, 3, 4, 5, 6]
// your code here
for i in listOfNumbers
.intersection(otherNumbers)
.sorted() {
print(i)
}
Intersection (sorry, watching football!)
I’m getting a runtime error on the even test cases on problem 6.6 with this code:
var listOfNumbers = [2, 5, 7, 23]
// your code here
var j = listOfNumbers.count – 1
var i = 0
var tmp = 0
while i != j{
tmp = listOfNumbers[i];
listOfNumbers[i] = listOfNumbers[j]
listOfNumbers[j] = tmp
i += 1
j -= 1;
}
***End of Code***
The error happens on the line with “tmp = listOfNumbers[i]”
Any ideas on how to fix this? I implemented this algorithm in C using a for loop with relative ease. Wish swift 3 didn’t get rid of the C-style for-loop
RIP
By even test cases I mean that the number of elements in listOfNumbers is even
(i.e: listOfNumbers.count % 2 == 0 is True)
I got it. Here’s what i did instead:
var j = listOfNumbers.count – 1
var sizeOfArray = listOfNumbers.count
for i in 0..<sizeOfArray/2 {
var tmp = listOfNumbers[i]
listOfNumbers[i] = listOfNumbers[j]
listOfNumbers[j] = tmp
j -= 1
}
**End**
IMHO, I think this is a less elegant, less obvious solution to what could have been accomplished with a C-style loop, but maybe that's because they're teaching me C in my CS class right now lol.
Do you know why they got rid of C loops in swift 3? If you know, that would be a good blog post, I believe.
Here’s my solution for 6.11, but I like the way you use booleans. Much cleaner code, imo.
var numbers = [12, 36, 720, 18]
// your code here
var gcd = 1
var min = numbers[0]
for i in numbers {
if i 0 {
if numbers[numbers.count – t] % i == 0 {
count += 1
}
if count == numbers.count {
gcd = i
}
t-=1
}}
print(gcd)
oops I think I didn’t copy/paste it all
var gcd = 1
var min = numbers[0]
for i in numbers {
if i 0 {
if numbers[numbers.count – t] % i == 0 {
count += 1
}
if count == numbers.count {
gcd = i
}
t-=1
}}
print(gcd)
nvm it might be the comment box. last try:
var gcd = 1
var min = numbers[0]
for i in numbers {
if i 0 {
if numbers[numbers.count – t] % i == 0 {
count += 1 }
if count == numbers.count {
gcd = i }
t-=1
}}
print(gcd)