Swift Programming – Collection Types

In this tutorial you’ll learn about collection types in Swift. To follow along, it is recommended to have a Mac and the Xcode IDE installed on it. This tutorial makes use of the Xcode playground for compilation of the Swift codes. If you do not have a Mac, you may try using the open-source code editors which support different operating systems such as Atom, SublimeText or VSCode.

Collection Types

There are three primary collection types in Swift for storing of collections values:

  • Arrays
  • Sets
  • Dictionaries

Arrays

You use an array when you want to store an ordered collections of values.

Creating an Empty Array

You can create an empty array of a certain type and then append values to it. If an array has some values in it, you can set it to empty.

var numbers = [Int]() // empty array
numbers.append(15) // array has 1 value where numbers now become [15]
numbers = [] // setting the array back to empty

Creating an Array with a Default Value

You can create an array for a specific size with same default values.

let points = Array(repeating: 0.0, count: 2) // [0.0, 0.0]

Creating an Array by Adding Two Arrays Together

You can combine two arrays of same types.

let coordinates = Array(repeating: 3.3, count: 2) // [3.3, 3.3]
let result = points + coordinates // [0.0, 0.0, 3.3, 3.3]

Creating an Array with an Array Literal

You can create an array using an array literal which means writing a list of values separated by commas and surrounding them with a pair of square brackets.

var groceryList = ["Fruits", "Yogurt", "Vegetables"]

Accessing and Modifying an Array

If you have to find out if an array contains some values, you can either use the ‘count’ property or the Boolean ‘isEmpty’ property.

print("groceryList contain \(groceryList.count) items") // groceryList.count returns 3

if groceryList.isEmpty {
    print("No need to go to the supermarket")
} else { // groceries is not empty therefore groceryList.isEmpty returns false
    print("Need to buy groceries")
}

You can use the ‘append’ method to append new items to the groceryList.

groceryList.append("Bread")

Alternatively, you can use the addition assignment operator (+=) to append one or more items to the groceryList.

groceryList += ["Milk", "Coffee", "Tea"]

You can get the first item in the groceryList by using subscript syntax, which means passing the index of the item you want to retrieve. Index starts with 0 in Swift, which means that to get the first item of the groceryList, you should pass the index 0.

var firstItem = groceryList[0]

You can use the subscript syntax to change an existing value at a given index.

groceryList[0] = "Apple"
firstItem = groceryList[0]

You can use the subscript syntax to change a range of existing values.

groceryList[2...4] = ["Broccoli", "Carrot"]

You can insert a new item at a specific index using the insert(_:at:) method.

groceryList.insert("Kiwi", at: 0)

You can remove an item at a specific index using the remove(at:) method.

groceryList.remove(at: 0)

If you want to remove the last item in the groceryList, instead of putting the last index in the remove(at:) method, you can use the removeLast() method.

groceryList.removeLast()

Iterating Over an Array

You can iterate over the groceryList’s items using the for-in loop.

for item in groceryList {
    print("item is \(item)")
}

If you need the index and value while iterating you can use the enumerated() method.

for (index, value) in groceryList.enumerated() {
    print("item at \(index) is \(value)")
}

Sets

You use a set when you want to store an unordered collections of unique values.

Hash Values for Set Types

In order to store a value in a set, you must make sure that its type is hashable, which means that the type must provide a way to compute a hash value for itself. A hash value is an Int value which is the same for all objects compared equally, for example, x == y follows that x.hashValue == y.hashValue. All basic types of Swift (Int, Double, Bool and String) are hashable by default.

Creating and Initializing an Empty Set

You can create an empty set of a certain type and then insert values in it. If a set has some values in it, you can set it to empty.

var alphabets = Set<Character>() // empty set
alphabets.insert("a") // set has 1 value where alphabets now become ["a"]
alphabets = [] // setting the set back to empty

Creating a Set with an Array Literal

You can create a set using an array literal which means writing a list of values separated by commas and surrounding them with a pair of square brackets.

var favoriteTvShows: Set = ["Charmed", "Prison Break", "Money Heist"]

Accessing and Modifying a Set

If you have to find out if a set contains some values, you can either use the ‘count’ property or the Boolean ‘isEmpty’ property.

print("favoriteTvShows contain \(favoriteTvShows.count) items") // favoriteTvShows.count returns 3

if favoriteTvShows.isEmpty {
    print("I like most of the popular tv shows")
} else { // favoriteTvShows is not empty therefore favoriteTvShows.isEmpty returns false
    print("I have some favorite tv shows")
}

You can insert a new item using the insert(_:) method.

favoriteTvShows.insert("The Flash")

You can remove an item using the remove(_:) method.

if let removedTvShow = favoriteTvShows.remove("Charmed") {
    print("I have watched \(removedTvShow) too many times")
} else {
    print("Tv show 'Charmed' is not in my favorite tv show set")
}

You can check if an item exists in a set.

if favoriteTvShows.contains("Prison Break") {
    print("I have reached Season 3")
} else {
    print("I have watched all the seasons of my favorite tv shows")
}

Iterating Over a Set

You can iterate over the favoriteTvShow’s items using the for-in loop.

for favoriteTvShow in favoriteTvShows {
    print(favoriteTvShow)
}

You can iterate over the favoriteTvShow’s items in a sorted way.

for favoriteTvShow in favoriteTvShows.sorted() {
    print(favoriteTvShow)
}

Performing Set Operations

You can perform the following set operations on two given sets:

  • intersection(_:) – creates a new set with only the common values found in both sets.
  • symmetricDifference(_:) – creates a new set with only the values found not common in both sets.
  • union(_:) – creates a new set with values of both sets.
  • subtracting(_:) – creates a new set with values not found in the specified set.
let evenNumbers: Set = [2, 4, 6, 8, 10]
let oddNumbers: Set = [1, 3, 5, 7, 9]
let primeNumbers: Set = [2, 3, 5, 7]

let intersectionEvenPrimeNumbers = evenNumbers.intersection(primeNumbers)
print("The intersection of the even numbers \(evenNumbers.sorted()) with the prime numbers \(primeNumbers.sorted()) is \(intersectionEvenPrimeNumbers.sorted())")

let symmeticDifferenceOddPrimeNumbers = oddNumbers.symmetricDifference(primeNumbers)
print("The symmetric difference of the odd numbers \(oddNumbers.sorted()) with the prime numbers \(primeNumbers.sorted()) is \(symmeticDifferenceOddPrimeNumbers.sorted())")

let unionEvenOddNumbers = evenNumbers.union(oddNumbers)
print("The union of the even numbers \(evenNumbers.sorted()) with the odd numbers \(oddNumbers.sorted()) is \(unionEvenOddNumbers.sorted())")

let subtractingOddPrimeNumbers = oddNumbers.subtracting(primeNumbers)
print("The subtracting of the odd numbers \(oddNumbers.sorted()) with the prime numbers \(primeNumbers.sorted()) is \(subtractingOddPrimeNumbers.sorted())")

Set Membership and Equality

You can use the is equal to (==) operator to check if two sets contain the same values. Furthermore, you can use the following methods to perform some intended operations:

  • isSubset(of:) – to check if all elements in a set are contained in another set.
  • isSuperset(of:) – to check if a set contains all the values of another set.
  • isStrictSubset(of:) or isStrictSuperset(of:) – to check if a set is a subset or superset but not equal to another set.
  • isDisjoint(with:) – to check if two sets have no common values.
let numberSet: Set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sortedSet = numberSet.sorted()

if unionEvenOddNumbers.sorted() == sortedSet {
    print("numberSet \(sortedSet) is equal to union of the even numbers \(unionEvenOddNumbers)")
}

if numberSet.isSubset(of: unionEvenOddNumbers) {
    print("numberSet \(sortedSet) are subset of \(unionEvenOddNumbers.sorted())")
}

if unionEvenOddNumbers.isSuperset(of: numberSet) {
    print("unionEvenOddNumbers \(unionEvenOddNumbers.sorted()) is the superset of the odd numbers \(sortedSet)")
}

if primeNumbers.isStrictSubset(of: numberSet) {
    print("primeNumbers \(primeNumbers.sorted()) is strict subset of \(sortedSet)")
}

if numberSet.isStrictSuperset(of: evenNumbers) {
    print("numberSet \(sortedSet) is strict superset of \(evenNumbers.sorted())")
}

let randomNumbers: Set = [11, 14, 16, 17, 20]

if oddNumbers.isDisjoint(with: randomNumbers) {
    print("oddNumbers \(oddNumbers.sorted()) is disjoint with \(randomNumbers.sorted())")
}

Dictionaries

You use a Dictionary when you want to store an unordered collections of key-value associations. A key type in a dictionary must conform to the Hashable protocol similar to a set’s value type.

Creating an Empty Dictionary

You can create an empty dictionary of a certain type and then add key-value to it. If a dictionary has some key-value items in it, you can set it to empty.

var records = [Int: String]() // empty dictionary
records[1] = "Swift" // dictionary has 1 key-value where records now become [1: "Swift"]
records = [:] // setting the dictionary back to empty

Creating a Dictionary with a Dictionary Literal

You can create a dictionary using a dictionary literal which means writing a list of key-value separated by commas and surrounding them with a pair of square brackets.

var countries = ["US": "United States of America", "UK": "United Kingdom", "FR": "France", "MU": "Mauritius"]

Accessing and Modifying a Dictionary

If you have to find out if a dictionary contains some values, you can either use the ‘count’ property or the Boolean ‘isEmpty’ property.

print("countries contain \(countries.count) items") // countries.count returns 4

if countries.isEmpty {
    print("No countries found")
} else { // countries is not empty therefore countries.isEmpty returns false
    print("Some countries found")
}

You can add a new item using the subscript syntax.

countries["AU"] = "Australia"
countries["CA"] = "CA"
countries["GR"] = "GR"

You can update a value using the subscript syntax or the updateValue(forKey:) method.

countries["CA"] = "Canada"
countries.updateValue("Greece", forKey: "GR")

You can retrieve a value using the subscript syntax.

if let retrievedValue = countries["MU"] {
    print("\(retrievedValue)'s country code is MU")
} else {
    print("No such key was found")
}

You can remove a value using the subscript syntax or the removeValue(forKey:) method.

countries["CA"] = nil

if let removedValue = countries.removeValue(forKey: "AU") {
    print("\(removedValue) has been removed from \(countries)")
} else {
    print("No such key was found")
}

Iterating Over a Dictionary

You can iterate over the countries’ items using the for-in loop.

for (countryCode, country) in countries {
    print("Code \(countryCode) is for \(country)")
}

Additionally, you can iterate over the countries’ keys only or values only.

for code in countries.keys {
    print("Code is \(code)")
}

for country in countries.values {
    print("Country is \(country)")
}

Reference

https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html