The count property
An array reports how many elements it holds through its count property. Unlike in several other languages, there is no length in Swift. The count of an array that changes follows the changes:
var ourArray = [50, 40, 30]
print(ourArray.count) // 3
ourArray.remove(at: 2)
print(ourArray.count) // 2
ourArray.append(10)
ourArray.append(20)
print(ourArray.count) // 4
Each call to count reads the current size, so you never have to keep a separate counter up to date. The value is an Int. It is a property, so you write ourArray.count without parentheses.
Counting is not the same as indexing
Indexes start at 0, so the valid indexes of an array run from 0 to count - 1. With three elements the count is 3, but the highest valid index is 2. This is the source of most off-by-one mistakes with arrays.
Using count to reach the end
Store the count in a constant, or use it inline, to read items from the end of the array:
var ourArray = [50, 40, 30]
let count = ourArray.count
print(ourArray[count - 1]) // 30, the last item
print(ourArray[count - 2]) // 40, the second to last item
The expression count - 1 is evaluated first and gives the index of the last element. This stays correct however long the array is.
last and first
Arrays also have first and last properties. They return optionals, because an empty array has neither. [50, 40, 30].last is Optional(30) and has to be unwrapped before you can calculate with it. Indexing with count - 1 gives a plain Int, which is what the exercise below uses.
Empty arrays
An empty array has a count of 0, and isEmpty is true. Reaching for count - 1 there gives -1, an invalid index, so check isEmpty before reading from the end of an array that might be empty.
Count in loops
The count sets the bounds of a loop. The range 0..<ages.count stops before the count, so it produces exactly the valid indexes 0, 1, 2 and 3 for a four-element array. Counting down from the end uses count - 1 as the starting index:
let ages = [14, 32, 50, 21]
var i = ages.count - 1
while i >= 0 {
print(ages[i], terminator: " ")
i -= 1
}
// prints: 21 50 32 14
Integer division gives a middle element: ages[ages.count / 2] is index 2 here, which holds 50. Division of integers drops the fraction, so for an odd count it lands on the true middle.
A safe way to read the last element of an array that might be empty is to test first: ages.isEmpty ? -1 : ages[ages.count - 1] gives 21 for ages and -1 for an empty array.
The exercise, step by step
The starter code declares fruits with three items and ages with four.
- Print the count of
fruits.print(fruits.count)prints3. - Print the last age. Index
ages.count - 1, which is 3:print(ages[ages.count - 1])prints21. - Print the second to last age. Subtract 2 instead:
print(ages[ages.count - 2])reads index 2 and prints50.
var fruits = ["mango", "kiwi", "grapefruit"]
var ages = [14, 32, 50, 21]
print(fruits.count)
print(ages[ages.count - 1])
print(ages[ages.count - 2])
The three lines of output are 3, 21 and 50.
Common mistakes
- Adding parentheses.
ages.count()doesn't compile, becausecountis a property. - Using
countas the last index.ages[ages.count]is one past the end and crashes at run time. - Using
length. Arrays have nolengthproperty in Swift. - Reading the count too early. A constant like
let count = ourArray.countholds the size at that moment. If the array changes afterwards, readcountagain.
Key takeaways
countgives the current number of elements and followsappendandremove(at:).- The last valid index is
count - 1. lastis an optional;array[array.count - 1]is a plain value.- An empty array has a
countof 0.
