Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

array
An ordered list of values of one type, reached by position starting at zero.
block
A group of lines of code that run together, often inside curly brackets.
closure
A piece of code you can store in a value and pass to other code, remembered with the names around it.
compiler
The program that turns the code you write into something the machine can run, reporting mistakes before it does.
dictionary
A collection of key and value pairs, where each key appears once and finds its value.
enum
A type whose value is one of a fixed set of named cases, which may each carry extra data.
expression
A piece of code that produces a value, such as a sum or a call to a function.
function
A named piece of code that takes values and returns a result when called.
guard
A check that must pass before the code after it runs, leaving the scope early when it fails.
method
A function that belongs to a type and is called on a value of that type.
nil
The absence of a value, allowed only where a type says a value may be missing.
operator
A symbol such as plus or equals that combines values into a new one.
optional
A type that either holds a value or holds nothing, written with a question mark after the type.
optional chaining
Writing a question mark before something you reach into, so the result is nil when the value is missing.
property
A named value that belongs to a type or to one of its values.
protocol
A list of requirements that a type promises to meet, so code can work with any type that meets them.
scope
The region of code where a name can be used before it goes out of reach.
string interpolation
Putting a value inside text with a backslash and parentheses, so the value becomes part of the text.
struct
A type that groups related values and makes a copy whenever it is given another name or passed along.
subscript
A way to read or write an item in an array or dictionary by putting a key or position in square brackets.
type
What kind of value something is, such as a whole number or text, and what it can do.
unwrap
To get the value out of an optional after checking that something is there.

Swift from the ground up

Arrays and dictionaries

Lists that keep order, keyed lookups, and the four tools that work on a whole collection at once.

Part 8 of 12

Intermediate18 min readBack to Courses

A list of values

An array holds an ordered list. [90, 75, 82] makes one, and the type is written [Int]. Positions start at zero, so the first value is at index zero, and .count gives how many there are.

A var array can grow with .append(...) and be reordered with .sorted(). Store it with let when the list itself should not change.

first and last return optionals, because an empty array has neither. Subscripting with [0] does not: it returns a plain element and stops the program when the index is out of range. That difference is deliberate — a position you chose is assumed to exist, while the first item may genuinely be absent.

Working on the whole list

Four tools save you from writing loops. .map changes every value into a new value, .filter keeps the ones that pass a test, .sorted puts them in order, and .reduce folds the whole list into a single answer.

Each takes a small block of code that says what to do with one item. A short block can use $0 for the item and $1 for the second one, which keeps the line tight.

The methods chain because each returns a new array. scores.filter { $0 >= 75 }.map { $0 / 10 } keeps the passing scores, then divides each one, and the second block only ever sees values that passed. Reading the chain left to right is reading the order the work happens in.

Dictionaries: keys and values

A dictionary looks up a value by a key instead of a position. ["Ada": 36] maps the key "Ada" to the value 36, and the type is written [String: Int].

Looking up a key gives an optional, because the key may not be there. That is the optional from the last chapter doing its usual job: the answer may be missing, and you handle it.

Assigning nil to a key removes it: ages["Alan"] = nil deletes the entry rather than storing a missing value. The default: subscript is the other useful form, counts[word, default: 0] += 1, which reads the old count or zero, adds one, and writes it back without an optional in sight.

Arrays are values, dictionaries are unordered

An array is a value. var copy = scores makes a second array, and changing one does not change the other. Swift shares the storage until a write happens, so the copy is cheap, but the behaviour you see is a true copy.

A dictionary is not ordered. Its keys come back in whatever order the table finds convenient, so sort them before printing. keys.sorted() gives a steady order and makes two runs comparable.

Because arrays are values, assigning one to another copies it; changing the copy does not change the original, which is the opposite of a reference type.

A dictionary key must be Hashable, which means it can be reduced to an integer the table can use as a starting point. String, Int and most simple values qualify. The hash is not the value’s identity; two equal keys must hash the same, and the table then compares them properly to settle a collision.

A worked chain

Take [90, 75, 82, 60]. filter { $0 >= 75 } keeps 90, 75 and 82. map { $0 / 10 } turns them into 9, 7 and 8, using whole-number division. reduce(0, +) adds 24. The original array is untouched at every step, so it can be used again for a different report.

The same result can be written as a loop with a running total, and for a very long array that is often faster. The chain is shorter and says what happens rather than how: keep, transform, fold. Choose the form that makes the intent obvious, and reach for the loop when the intermediate arrays become the cost that matters.

Four tools and one lookup

var numbers = [3, 1, 4, 1, 5]
numbers.append(9)
print(numbers.sorted())

let doubled = numbers.map { $0 * 2 }
let big = numbers.filter { $0 > 3 }
let total = numbers.reduce(0, +)

var ages = ["Ada": 36]
ages["Alan"] = 41
print(ages.keys.sorted())

Three mistakes cause most collection bugs. An index must be less than count, because the last valid position is count - 1. A dictionary lookup returns an optional even for a key that looks familiar, so open it or give it a fallback. And sorted() returns a new array while sort() changes the one you call it on; choosing the wrong one either loses the order or fails on a let.

A list of scores, a table of ages

Run it and check the totals. Then add one more score to the list and predict how the count, the passing list and the total change.

Output
Click "Run" to execute your code

Try these next

  • Add three numbers to an array, then print the first, the last and the count.
  • Build a dictionary in a loop, then print its keys sorted by name.
  • Take a list of scores, keep the passing ones, double them, and sum the result in one chain.

Count the words in a list

Run it and check each frequency. Then add another repeated word and predict which counts change and which stay the same.

Output
Click "Run" to execute your code

Sorting a dictionary by its keys before printing gives a steady, predictable order. That habit keeps output the same every run and makes reports easy to read.

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What does map give when its block doubles each value?