An array in Swift is an ordered collection of values. It is written as Array<Element>
or in a shorthand form using square brackets [Element]
where element is the type of values stored in the array.
Below is a basic example of creating an immutable array, getting values from that array, and getting the number of items in the array. Notice that the first item in the array is at index 0.
let a = Array([4, 5, 8, 6, 10, 12, 17])
print("a is \(a)")
print("a[0] is \(a[0])")
print("a[2] is \(a[2])")
print("a.count is \(a.count)")
// a is [4, 5, 8, 6, 10, 12, 17]
// a[0] is 4
// a[2] is 8
// a.count is 7
Here is a basic example of a creating a mutable array and changing the first item in the array.
var b = [4, 5, 6, 7, 8]
b[0] = 99
print("b is \(b)")
// b is [99, 5, 6, 7, 8]
This example creates an empty array and appends integer values to the array.
var c: [Int] = []
c.append(2)
c.append(10)
c.append(19)
print("c is \(c)")
// c is [2, 10, 19]
There are several approaches to creating an array of random numbers in Swift. This example creates an array filled with zeros, then assigns a random number to each element in the array. Notice the random number is within a range of values which is from 0 to 1 in this example.
var x = [Float](repeating: 0, count: 5)
for i in 0..<x.count {
x[i] = .random(in: 0...1)
}
// x is [0.8209822, 0.85707325, 0.10973239, 0.119954765, 0.19724935]
Another approach is to map a random number to each array element as shown in the following example. The size of the array is determined by the range that is mapped.
let x = (0..<5).map { _ in Float.random(in: 0...1) }
// x is [0.4514997, 0.41597754, 0.04589182, 0.07227373, 0.9754954]
let z = (1...6).map { _ in Float.random(in: 1...10) }
// z is [2.7215362, 3.2972493, 2.9972453, 7.1019344, 8.892759, 3.715058]
However, the fastest approach for very large arrays is to use functions from the Accelerate framework. In this example, arc4random is used to assign random integers to the array. The integers are converted to Double then multiplied by a scaling factor such that the range of values are from 0 to 1.
import Accelerate
let n = 5
var x = [UInt32](repeating: 0, count: n)
arc4random_buf(&x, n * MemoryLayout<UInt32>.size)
var y = vDSP.integerToFloatingPoint(x, floatingPointType: Double.self)
cblas_dscal(Int32(n), 1 / Double(UInt32.max), &y, 1)
// y is [0.8341360464305934, 0.24041946028369002, 0.04481290514692965, 0.6746670607651274, 0.7728101240407699]
And yet another approach is to use the vDSP multiply function as shown below.
import Accelerate
let n = 5
var x = [UInt32](repeating: 0, count: n)
arc4random_buf(&x, n * MemoryLayout<UInt32>.size)
let y = vDSP.integerToFloatingPoint(x, floatingPointType: Double.self)
let c = 1 / Double(UInt32.max)
let z = vDSP.multiply(c, y)
// z is [0.7841595014986023, 0.12211232844789334, 0.6589130530271011, 0.4871890585606892, 0.2029429211288092]
The table below compares the approaches discussed above for creating a large array that contains 1,000,000 random numbers where each random number has a value from 0 to 1. The elapsed time in seconds to create the array is given in the second column. Notice how the Accelerate examples are about 30x faster than the Swift for-loop and map examples.
Random array example | Elapsed time (s) |
---|---|
Swift for-loop | 1.1609 |
Swift map | 1.0556 |
Accelerate BLAS Double | 0.0364 |
Accelerate BLAS Float | 0.0374 |
Accelerate vDSP Double | 0.0396 |
Accelerate vDSP Float | 0.0345 |
A range of numbers can be used to create an array as shown below.
let zz = Array(1...10)
print("zz is \(zz)")
// zz is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Get the first and last items of an array as shown here.
let x = [4, 5, 1, 9, 7]
if let firstItem = x.first {
print("x.first item is \(firstItem)")
}
// x.first item is 4
if let lastItem = x.last {
print("x.last item is \(lastItem)")
}
// x.last item is 7
The for-in loop will iterate over all the items in an array. To get the index associated with each value use the enumerated()
method.
let names = ["Homer", "Bart", "Marge", "Crusty", "Lisa"]
for n in names {
print("name is \(n)")
}
// name is Homer
// name is Bart
// name is Marge
// name is Crusty
// name is Lisa
for (i, n) in names.enumerated() {
print("index \(i), name \(n)")
}
// index 0, name Homer
// index 1, name Bart
// index 2, name Marge
// index 3, name Crusty
// index 4, name Lisa
Create an array of structs where properties of the structs are mapped to array values.
let xpts: [Float] = [1, 2, 3, 4, 5, 6]
let ypts: [Float] = [3, 4.5, 8, 7, 10, 2.2]
struct Point {
let x: Float
let y: Float
}
let points = zip(xpts, ypts).map { Point(x: $0, y: $1) }
for pt in points {
print("x is \(pt.x), y is \(pt.y)")
}
// x is 1.0, y is 3.0
// x is 2.0, y is 4.5
// x is 3.0, y is 8.0
// x is 4.0, y is 7.0
// x is 5.0, y is 10.0
// x is 6.0, y is 2.2
Gavin Wiggins © 2024