The introduction

Continuing with the Swift documentation, we learned about Swift strings and characters from the previous section: Strings and Characters. The data structure of collection is also frequently used in our project development process, so it is necessary to master its usage. Now, let’s start learning about Swift’s collection. Due to the long space, here is a section to record, next, let’s begin!

If you’re already familiar with collections, read the next section: Control Flow

Collection types

Swift provides three main collection types, arrays, collections, and dictionaries, for storing collections of values. An array is an ordered collection of values. Collections are unordered collections of unique values. Dictionaries are unordered collections of key-value associations.

Notice that Swift’s array, set, and Dictionary types are implemented as generic collections. For more information about generic types and collections, see Generics.

1 Mutable set

If you create an array, a collection, or a dictionary and assign it to a variable, the collection you create will be mutable. This means that you can change (or change) collections after they are created by adding, deleting, or changing items in the collection. If an array, collection, or dictionary is assigned to a constant, the collection is immutable and its size and content cannot be changed.

Note that it is a good practice to create immutable collections when all collections do not need to change. Doing so makes it easier for you to reason about your code and enables the Swift compiler to optimize the performance of the collections you create.

2 array

Arrays store values of the same type in an ordered list. The same value can appear multiple times in different places in the array.

Note that Swift’s array type is bridged to Foundation’s NSArray class.

For more information about using arrays in Foundation and Cocoa, see Bridging between Array and NSArray.

2.1 Array type shorthand syntax

The type of the Swift array is written as array, where Element is the type of value the array is allowed to store. You can also abbreviate the type of the array to [Element]. Although both forms are functionally the same, the shorthand form is preferred and will be used throughout this guide when referring to array types.

2.2 Creating an empty Array

You can create an empty array of a specific type using the initialization syntax:

var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."
Copy the code

Alternatively, if the context already provides type information, such as a function parameter or a typed variable or constant, you can create an empty array with an empty array literal, which reads:

someInts.append(3)
// someInts now contains 1 value of type Int
someInts = []
// someInts is now an empty array, but is still of type [Int]
Copy the code

2.3 Creating arrays with Default Values

Swift’s array type also provides an initializer to create an array of a specific size, all of which are set to the same default values. You pass the initializer a default value of the appropriate type (called repeat): and the number of times that value is repeated in the new array (called count):

Var threeDoubles = Array(repeating: 0.0, Count: 3) // threeDoubles is oftype[Double], equals [0.0, 0.0, 0.0]Copy the code

2.4 Create an array by adding two arrays together

New arrays can be created by adding two existing arrays with compatible types using the addition operator (+). The type of the new array is inferred from the types of the two arrays you add together:

Var anotherThreeDoubles = Array(repeating: 2.5, Count: 3) // anotherThreeDoubles is oftype[Double], equals [2.5, 2.5, Var sixDoubles = threeDoubles + anotherThreeDoubles // sixDoubles is equal as [doubles], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]Copy the code

2.5 Create arrays with array literals

You can also initialize an array with array literals, which is a shorthand way of writing one or more values to an array collection. An array literal is written as a list of values, separated by commas and surrounded by square brackets:

[value 1, value 2, value 3]
Copy the code

The following example creates an array called shoppingList to store string values:

var shoppingList: [String] = ["Eggs"."Milk"]
// shoppingList has been initialized with two initial items
Copy the code

The shoppingList variable is declared as an “array of string values” and written as [string]. Because this particular array specifies the string value type, only string values are allowed to be stored. Here, the shoppingList array is initialized with two string values (” Eggs “and” Milk “), written in array literals.

Notice that the shoppingList array is declared as a variable (using the var importer), not a constant (using the let importer), because more items are added to the shoppingList in the example below.

In this case, the array literal contains only two string values. This matches the type of the shoppingList variable declaration (which can only contain arrays of string values), thus allowing assignment of array literals as a way to initialize the shoppingList with two initializers.

Because of Swift’s type inference, if you initialize an array with array text containing values of the same type, you don’t have to write the type of the array. The initialization of a shoppingList can be written in a shorter form:

var shoppingList = ["Eggs"."Milk"]
Copy the code

Because all the values in the array literal are of the same type, Swift can infer that [String] is the correct type for the shoppingList variable.

2.6 Accessing and modifying arrays

Arrays can be accessed and modified through their methods and properties or subscript syntax.

To find the number of items in an array, check its read-only count property:

print("The shopping list contains \(shoppingList.count) items.")
// Prints "The shopping list contains 2 items."
Copy the code

Use the Boolean attribute isEmpty as a shortcut to check if the count attribute is equal to 0:

if shoppingList.isEmpty {
    print("The shopping list is empty.")}else {
    print("The shopping list is not empty.")
}
// Prints "The shopping list is not empty."
Copy the code

You can add a new item to the end of the array by calling its append(_:) method:

shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes
Copy the code

Alternatively, append an array containing one or more compatible items using the addition assignment operator (+=) :

shoppingList += ["Baking Powder"]
// shoppingList now contains 4 items
shoppingList += ["Chocolate Spread"."Cheese"."Butter"]
// shoppingList now contains 7 items
Copy the code

Retrieve a value from an array using subscript syntax, passing the index of the value you want to retrieve in square brackets after the array name:

var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"
Copy the code

Notice that the first item in the array is indexed to 0, not 1. Arrays in Swift are always zero-indexed.

In a given index, you can change an existing value using subscript syntax:

shoppingList[0] = "Six eggs"
// the first item in the list is now equal to "Six eggs" rather than "Eggs"
Copy the code

When using subscript syntax, the specified index must be valid. For example, write shoppingList[shoppingList]. Trying to append an item to the end of an array causes a runtime error.

You can also use subscript syntax to change a range of values at once, even if the length of the replacement value set is different from the range to be replaced. The following example replaces “chocolate sauce”, “cheese” and “butter” with “banana” and “apple” :

shoppingList[4...6] = ["Bananas"."Apples"]
// shoppingList now contains 6 items
Copy the code

To insert an item at the index specified in the array, call the insert(_:at:) method of the array:

shoppingList.insert("Maple Syrup", at: 0)
// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list
Copy the code

This call to the Insert (_:at:) method will insert a new item with a value of “Maple Syrup” at the beginning of the shopping list, which is represented by index 0.

Similarly, remove an item from an array using the remove(at:) method. This method removes the item at the specified index and returns the removed item (although you can ignore the return value if you don’t need it):

let mapleSyrup = shoppingList.remove(at: 0)
// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string
Copy the code

Note that a runtime error is emitted if you attempt to access or modify an index value outside the existing bounds of the array. Before using an index, you can check that it is valid by comparing it to the count property of the array. The largest valid index in an array is count-1, because the index of the array starts at 0. However, when count is 0(meaning the array is empty), there is no valid index.

When an element is removed, any gaps in the array are closed, so the value at index 0 is once again equal to “Six eggs” :

firstItem = shoppingList[0]
// firstItem is now equal to "Six eggs"
Copy the code

If you want to remove the last item from the array, use the removeLast() method instead of the remove(at:) method to avoid querying the count property of the array. Like the remove(at:) method, removeLast() returns the deleted item:

let apples = shoppingList.removeLast()
// the last item in the array has just been removed
// shoppingList now contains 5 items, and no apples
// the apples constant is now equal to the removed "Apples" string
Copy the code

2.7 Traverse the number group

You can loop through all the values in the array using a for-in loop:

for item in shoppingList {
    print(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
Copy the code

If you need an integer index for each item and its value, you iterate through the array using the enumeration () method. For each item in the array, the enumeration () method returns a tuple of integers and items. Integers start at 0 and increment each term by 1; If you enumerate the entire array, the integers match the index of the item. You can decompose tuples into temporary constants or variables as part of an iteration:

for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
Copy the code

For more information about for-in loops, see for-In loops.

3 set

Collections store different values of the same type in collections with no defined order. If the order of the items is not important, or if you need to ensure that the items appear only once, you can use collections instead of arrays.

Note that Swift’s Set type is bridged to Foundation’s NSSet class. For more information about using sets in Foundation and Cocoa, see Bridging between Sets and NSSets.

3.1 Hashes of collection Types

In order to be stored in a collection, a type must be hashable-that is, it must provide a way to compute a hash for itself. A hash value is an integer value that is the same for all objects compared for equality, such that if A == b, it is a.hash value == B.hash value.

By default, all of Swift’s primitive types (such as string, Int, Double, and Bool) are Hashable and can be used as set value types or dictionary key types. Enumeration use case values without associated values (as described in enumerations) are hashable by default.

Note that by making them compliant with the Hashable protocol in the Swift standard library, you can use your own custom types as setting value types or dictionary key types. Types that conform to the Hashable protocol must provide an accessible Int attribute hashValue. The value returned by the hashValue attribute of a type need not be the same in different executions of the same program or in different programs.

Because the Hashable protocol conforms to Equatable, the conforming types must also provide an implementation of the equals operator (==). The Equatable protocol requires that any implementation that conforms to == be equivalent. That is, for all a, B, and C values, the implementation of == must satisfy the following three conditions:

  • A == b(reflexivity)
  • A == b means b == a(symmetric)
  • A == b && b == c means a == C (transitivity)

For more information about compliance, see Protocols.

3.2 Set type syntax

The type of the Swift collection is written as set, where Element is the type that the collection is allowed to store. Unlike arrays, there is no equivalent shorthand for collections.

3.3 Creating and initializing empty collections

An initializer can be used to create an empty collection of a specific type

var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// Prints "letters is of type Set<Character> with 0 items."
Copy the code

Note that based on the type of the initializer, it is inferred that the type of the letter variable is set to.

Alternatively, if the context already provides type information, such as function arguments or typed variables or constants, you can create an empty array literal:

letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
Copy the code

3.4 Create a collection with array literals

You can also initialize a set with array literals, which is a shorthand way of writing one or more values as a set.

The following example creates a collection called favoritegenre to store string values:

var favoriteGenres: Set<String> = ["Rock"."Classical"."Hip hop"]
// favoriteGenres has been initialized with three initial items
Copy the code

The favoritegenre variable is declared as “a set of string values,” written as set. Because this particular collection specifies the string value type, only string values are allowed to be stored. Here, the favoritegenre setting is initialized with three string values (” Rock, “” Classical” and “Hip Hop”), written in an array literal.

Note that the favoritegenre setting is declared as a variable (using the var importer) rather than a constant (using the let importer), because entries are added and deleted in the following example.

Collection types cannot be inferred from array literals alone, so the type set must be explicitly declared. However, because of Swift’s type inference, if you initialize a collection with an array literal that contains only one type of value, you don’t have to write the type of the collection element. The initial favoritegenre can be written in a shorter form instead:

var favoriteGenres: Set = ["Rock"."Classical"."Hip hop"]
Copy the code

Because all the values in the array text are of the same type, Swift can infer that Set is the right type to use the favoritegenre variable.

3.5 Accessing and Modifying collections

Access and modify collections through their methods and properties.

To find out the number of items in a collection, check its read-only count property:

print("I have \(favoriteGenres.count) favorite music genres.")
// Prints "I have 3 favorite music genres."
Copy the code

Use the Boolean attribute isEmpty as a shortcut to check if the count attribute is equal to 0:

if favoriteGenres.isEmpty {
    print("As far as music goes, I'm not picky.")}else {
    print("I have particular music preferences.")
}
// Prints "I have particular music preferences."
Copy the code

You can add new items to the collection by calling the insert(_:) method of the collection:

favoriteGenres.insert("Jazz")
// favoriteGenres now contains 4 items
Copy the code

You can remove an item from the collection by calling the remove(_:) method of the collection, which will remove the item if it is a member of the collection and return the removed value, or nil if the collection does not contain the value. Alternatively, you can use its removeAll() method to removeAll items in the collection.

if let removedGenre = favoriteGenres.remove("Rock") {
    print("\(removedGenre)? I'm over it.")}else {
    print("I never much cared for that.")
}
// Prints "Rock? I'm over it."
Copy the code

To check whether the collection contains a specific item, use the contains(_:) method.

if favoriteGenres.contains("Funk") {
    print("I get up on the good foot.")}else {
    print("It's too funky in here.")
}
// Prints "It's too funky in here."
Copy the code

3.6 Iterative Set

You can use a for-in loop to iterate over the values in a collection.

for genre in favoriteGenres {
    print("\(genre)")
}
// Classical
// Jazz
// Hip hop
Copy the code

For more information about for-in Loops, see For-in Loops.

Swift’s Set type has no defined order. To iterate over the values of a collection in a particular order, use the sorted() method, which returns the collection’s elements as an array and sorts them using the < operator.

for genre in favoriteGenres.sorted() {
    print("\(genre)")
}
// Classical
// Hip hop
// Jazz
Copy the code

4 Perform the set operation

You can efficiently perform basic collection operations, such as combining two collections together, determining what values two collections have in common, or determining whether two collections contain all the same values, some values, or none.

4.1 Basic Settings

The following figure depicts two sets (A and B) that are the result of various set operations represented by shaded areas.

  • Use the intersection (_:) method to create a new collection with only two values common to the collection.
  • Use the symmetricDifference(_:) method to create a new collection whose values are in both collections, but not both at the same time.
  • Use the union(_:) method to create a new collection that contains all the values in both collections.
  • Creates a new collection with the subtraction (_:) method whose value is not in the specified collection.
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
Copy the code

4.2 Set relation and equality

The figure below depicts three sets (A, B, and C), where overlapping areas represent elements shared between sets. Set A is a superset of set B, because A contains all the elements of B. Instead, set B is a subset of set A, because all the elements of B are also contained in A. Sets B and C do not intersect each other because they have no elements in common.

  • Use the is equal operator (==) to determine whether two sets contain the same elements.
  • Use isSubset(of:) to determine whether one set is a subset of another.
  • Use isSuperset(of:) to determine if one set is a superset of another.
  • Use isStrictSubset(of:) or isStrictSuperset(of:) to determine whether a set is a subset or superset, but not equal to the specified set.
  • Use the isDisjoint (with 🙂 method to determine if two collections do not have a common value.
let houseAnimals: Set = ["🐶"."🐱"]
let farmAnimals: Set = ["🐮"."🐔"."🐑"."🐶"."🐱"]
let cityAnimals: Set = ["🐦"."🐭"]

houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
Copy the code

5 a dictionary

Dictionaries store associations between keys of the same type and values of the same type in collections without defining an order. Each value is associated with a unique key that acts as an identifier for that value in the dictionary. Unlike items in arrays, items in dictionaries have no specified order. When you need to look up a value based on its identifier, you can use a dictionary in much the same way that you would use a real-world dictionary to look up the definition of a particular word.

Notice that Swift’s “dictionary” type Bridges to Foundation’s NSDictionary class.

For more information about using Dictionary in Foundation and Cocoa, see Bridging Dictionary and NSDictionary.

5.1 Abbreviations of dictionary types

Swift dictionaries are written as Dictionary <Key, Value>, where Key is the type of Value that can be used as a Dictionary Key, and Value is the type of Value that the Dictionary stores for those keys.

Note that the dictionary key type must conform to the hash protocol, such as the value type of the collection.

You can also write the shorthand dictionary type as [Key: Value]. Although both forms are functionally identical, the shorthand form is preferred and used in this guide when referring to dictionary types.

5.2 Creating an Empty Dictionary

As with arrays, we can use initialization syntax to create an empty dictionary of property types:

var namesOfIntegers = [Int: String]()
// namesOfIntegers is an empty [Int: String] dictionary
Copy the code

Create a [Int: String] dictionary where key is Int and value is String

If the context already provides type information, an empty dictionary can be created using an empty dictionary literal, written with [:] (colons inside square brackets) :

namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]
Copy the code

5.3 Creating a Dictionary with Dictionary text

You can also initialize the dictionary with dictionary text, which has similar syntax to the array text you saw earlier. Dictionary literals are a convenient way to write one or more key-value pairs as collections of dictionaries.

Key-value is a combination of key and value. In dictionary literals, keys and values in each key-value pair are separated by colons. The key-value pairs are written as lists, separated by commas and surrounded by square brackets:

[key 1: value 1, key 2: value 2, key 3: value 3]
Copy the code

The following example creates a dictionary to store the name of an international airport. In this dictionary, the key is the three-letter IATA code and the value is the airport name:

var airports: [String: String] = ["YYZ": "Toronto Pearson"."DUB": "Dublin"]
Copy the code

Airports is declared as a [String: String] dictionary, meaning that the key of the dictionary is a String and the value is a String.

Notice that airports is declared as a variable (var), not a constant (let), because new data needs to be added in the following example.

Airports the dictionary text is initialized to a dictionary that contains two key-value pairs. The first key value is “YYZ” and the value value is “Toronto Pearson”. The second key value is “DUB” and the value value is “Dublin”.

The dictionary contains two strings: String key-value pairs. The key-value pairs need to match the type of airports declaration (key and value can only be strings), so dictionary assignments are allowed as a way of initializing the Airports dictionary with two initial entries.

As with arrays, if you initialize a dictionary with a dictionary literal whose key and value have a consistent type, you don’t need to type the dictionary. The initialization of airports could have been written in a shorter form:

var airports = ["YYZ": "Toronto Pearson"."DUB": "Dublin"]
Copy the code

Because all the keys in the text have the same type with each other, and all the values have the same type, Swift can infer that [String: String] is the right type for the Airports dictionary.

5.4 Accessing and Modifying the Dictionary

You can access and modify dictionaries through their methods and attributes or by using subscript syntax.

As with arrays, you can find out the number of items in a dictionary by checking its read-only count property:

print("The airports dictionary contains \(airports.count) items.")
// Prints "The airports dictionary contains 2 items."
Copy the code

Use the Boolean isEmpty attribute as a shortcut to check if the count attribute is equal to 0:

if airports.isEmpty {
    print("The airports dictionary is empty.")}else {
    print("The airports dictionary is not empty.")
}
// Prints "The airports dictionary is not empty."
Copy the code

You can use subscript syntax to add new items to the dictionary. Use the new key of the appropriate type as the subscript index and assign the new value of the appropriate type:

airports["LHR"] = "London"
// the airports dictionary now contains 3 items
Copy the code

You can also use subscript syntax to change the value associated with a particular key:

airports["LHR"] = "London Heathrow"
// the value for "LHR" has been changed to "London Heathrow"
Copy the code

In addition to subscripts, you can use the dictionary’s updateValue(: forKey 🙂 method to set or update the value of a specific key. As in the subscript example above, if no key exists, the updateValue(: forKey 🙂 method sets the value of the key; If the key already exists, the value is updated. However, unlike subscripts, the updateValue(_ : forKey 🙂 method returns the old value after an update. This allows you to check whether updates have been made.

The updateValue (_ : forKey 🙂 method returns an optional value of the dictionary value type. For example, for dictionaries that store String values, this method returns type String? Or “Optional String” value. If an old value existed before the update, this optional value contains the old value of the key; Nil if no value exists:

if let oldValue = airports.updateValue("Dublin Airport".forKey: "DUB") {
    print("The old value for DUB was \(oldValue).")
}
// Prints "The old value for DUB was Dublin."
Copy the code

You can also retrieve the value of a particular key from a dictionary using subscript syntax. Because you can request a key that does not have any value, the subscript of the dictionary returns an optional value of the dictionary value type. If the dictionary contains the value of the requested key, the subscript returns an optional value containing the existing value of that key. Otherwise, the subscript returns nil:

if let airportName = airports["DUB"] {
    print("The name of the airport is \(airportName).")}else {
    print("That airport is not in the airports dictionary.")
}
// Prints "The name of the airport is Dublin Airport."
Copy the code

You can remove key/value pairs from the dictionary by assigning a nil value to the key using subscript syntax:

airports["APL"] = "Apple International"
// "Apple International" is not the real airport for APL, so delete it
airports["APL"] = nil
// APL has now been removed from the dictionary
Copy the code

Alternatively, use the removeValue (forKey 🙂 method to remove key/value pairs from the dictionary. This method deletes the key-value pair (if it exists) and returns the deleted value, or nil if none exists:

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("The removed airport's name is \(removedValue).")}else {
    print("The airports dictionary does not contain a value for DUB.")
}
// Prints "The removed airport's name is Dublin Airport."
Copy the code

5.5 Traversing the Dictionary

You can iterate through key/value pairs in a dictionary using a for-in loop. Each item in the dictionary is returned as a tuple (key, value), and you can decompose the tuple’s members into temporary constants or variables during iteration:

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}
// LHR: London Heathrow
// YYZ: Toronto Pearson
Copy the code

For more for-in Loops, see For-in Loops

You can also retrieve an iterable collection of keys or values of a dictionary by accessing its key or value properties:

for airportCode in airports.keys {
    print("Airport code: \(airportCode)")
}
// Airport code: LHR
// Airport code: YYZ

for airportName in airports.values {
    print("Airport name: \(airportName)")
}
// Airport name: London Heathrow
// Airport name: Toronto Pearson
Copy the code

If you need to use dictionary keys or values through an API with an Array instance, initialize a new Array with keys or values attributes:

let airportCodes = [String](airports.keys)
// airportCodes is ["LHR"."YYZ"]

let airportNames = [String](airports.values)
// airportNames is ["London Heathrow"."Toronto Pearson"]
Copy the code

Swift’s Dictionary type has no defined order. To iterate over the keys or values of a dictionary in a particular order, use the sorted() method on their key or value attributes.

conclusion

This article deals with collections: arrays, collections, and dictionaries. Collection initialization, access and modification, and traversal, these are the basic operations of the collection, through reading the above content, I believe you will have a familiar impression of them; Work with the code, and you’ll get a better impression. The data structure of collection is also frequently used in our project development process, so it is necessary to master its usage.

Finally, like a friend can give 👍 oh, your encouragement is my motivation, hey hey ~

Reference: Swift-collection Types

Previous section: Strings and characters

Next chapter: Control flow