忍者刘米米

5.Collection Types

Collection Types

Swift provides three primary collection types, known as arrays, sets, and dictionaries, for storing collections of values. Swift are always clear about the types of values and keys that they can store. This means that you cannot insert a value of the wrong type into a collection by mistake.

  • Arrays are ordered collections of values.
  • Sets are unordered collections of unique values.
  • Dictionaries are unordered collections of key-value associations

Mutability of Collections

Use letor var

It is good practice to create immutable collections in all cases where the collection does not need to change.

Arrays

An array stores values of the same type in an ordered list. The same value can appear in an array multiple times at different positions.

Array Type Shorthand Syntax

full as Array<Element>

shorthand form as[Element]

Create Array

Empty Array

1
2
3
4
5
6
7
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."

var someInts:[Int];
someInts = []
// someInts is now an empty array, but is still of type [Int]

Array with a Default Value

1
2
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]

Adding Two Arrays Together

1
2
3
4
5
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]

var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

Array Literal

1
2
3
4
5
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList has been initialized with two initial items

// shorter form
var shoppingList = ["Eggs", "Milk"]

Array count

the largest valid index in an array will always be count - 1, because arrays are indexed from zero.

Find out the number of items

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

Checking count

1
2
3
4
5
6
if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list is not empty.")
}
// Prints "The shopping list is not empty."

Add a new item

1
2
3
4
5
6
7
8
//  add a new item to the end
shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes

shoppingList += ["Baking Powder"]
// shoppingList now contains 4 items
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList now contains 7 items

Subscript syntax

Retrieve a value

You can’t use subscript syntax to append a new item to the end of an array.

1
2
var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"

Change an existing value

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

Change a range of values

1
2
shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList now contains 6 items

Insert an item

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

Remove an item

returns the removed item

1
2
3
4
5
6
let mapleSyrup = shoppingList.remove(at: 0)
// the item that was at index 0 has just been removed

let apples = shoppingList.removeLast()
// to avoid the need to query the array’s count property
// the last item in the array has just been removed

Iterating Over an Array

Only value

1
2
3
4
5
6
7
8
for item in shoppingList {
print(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas

Integer index with value

1
2
3
4
5
6
7
8
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

Sets

A set stores distinct values of the same type in a collection with no defined ordering.

When to use

  • You can use a set instead of an array when the order of items is not important,
  • or when you need to ensure that an item only appears once.

Hash Values for Set Types

  • A type must be hashable in order to be stored in a set—that is, the type must provide a way to compute a hash value for itself.
  • All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default
  • Enumeration case values without associated values are also hashable by default.
  • custom types:conform to the Hashable protocol from Swift’s standard library ( gettable Int property called hashValue)
  • Hashable protocol conforms to Equatable, conforming types must also provide an implementation of the equals operator (==).

Set Type Syntax

Set<Element>

Creating and Initializing an Empty Set

1
2
3
4
5
6
7
8
9
10
11
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."

// Alternatively, if the context already provides type information
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>

Creating a Set with an Array Literal

1
2
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items

A set type cannot be inferred from an array literal alone, so the type Set must be explicitly declared.

1
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

Accessing and Modifying a Set

Find out the number of items

1
2
print("I have \(favoriteGenres.count) favorite music genres.")
// Prints "I have 3 favorite music genres."

Checking isEmpty

1
2
3
4
5
6
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."

Add a new item

1
2
favoriteGenres.insert("Jazz")
// favoriteGenres now contains 4 items

Remove item

all items in a set can be removed with its removeAll() method.

1
2
3
4
5
6
7
// return nil or removed value
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."

Check ifcontains

1
2
3
4
5
6
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."

Iterating Over a Set

1
2
3
4
5
6
for genre in favoriteGenres {
print("\(genre)")
}
// Jazz
// Hip hop
// Classical

Swift’s Set type does not have a defined ordering. To iterate over the values of a set in a specific order, use the sorted() method, which returns the set’s elements as an array sorted using the < operator.

1
2
3
4
5
6
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// Classical
// Hip hop
// Jazz

Performing Set Operations

Fundamental Set Operations

此处应有图

1
2
3
4
5
6
7
8
9
10
11
12
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]

Set Membership and Equality

此处应有图

1
2
3
4
5
6
7
8
9
10
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]

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

Dictionaries

Dictionary Type Shorthand Syntax

Dictionary<Key, Value>

shorthand form as [Key: Value]

  • A dictionary Key type must conform to the Hashable protocol, like a set’s value type
  • All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default
  • Enumeration case values without associated values are also hashable by default.
  • custom types:conform to the Hashable protocol from Swift’s standard library ( gettable Int property called hashValue)
  • Hashable protocol conforms to Equatable, conforming types must also provide an implementation of the equals operator (==).

Creating an Empty Dictionary

1
2
3
4
5
6
7
8
var namesOfIntegers = [Int: String]()
// namesOfIntegers is an empty [Int: String] dictionary

// If the context already provides type information
namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]

Creating a Dictionary with a Dictionary Literal

1
2
3
4
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

// shorter form instead:
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

Dictionary count

Find out the number of items

1
2
print("The airports dictionary contains \(airports.count) items.")
// Prints "The airports dictionary contains 2 items."

Checking isEmpty

1
2
3
4
5
6
if airports.isEmpty {
print("The airports dictionary is empty.")
} else {
print("The airports dictionary is not empty.")
}
// Prints "The airports dictionary is not empty."

Subscript

Add a new item

1
2
airports["LHR"] = "London"
// the airports dictionary now contains 3 items

Retrieve a value

a dictionary’s subscript returns an optional value (value or nil)

1
2
3
4
5
6
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."

Remove a key-value pair

assigning a value of nil for that key

1
2
3
4
5
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

Accessing method

Set new value or Change old value

the method returns a value of type String?, or “optional String”. This optional value contains the old value for that key if one existed before the update, or nil if no value existed

1
2
3
4
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.

Remove a key-value pair

returns the removed value, or returns nil

1
2
3
4
5
6
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."

Iterating Over a Dictionary

Swift’s Dictionary type does not have a defined ordering. To iterate over the keys or values of a dictionary in a specific order, use the sorted() method on its keys or values property.

1
2
3
4
5
for (airportCode, airportName) in airports {
print("\(airportCode): \(airportName)")
}
// YYZ: Toronto Pearson
// LHR: London Heathrow

Accessing Key and Value

retrieve an iterable collection of a dictionary’s keys or values

1
2
3
4
5
6
7
8
9
10
11
for airportCode in airports.keys {
print("Airport code: \(airportCode)")
}
// Airport code: YYZ
// Airport code: LHR

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

key or value become array

1
2
3
4
5
let airportCodes = [String](airports.keys)
// airportCodes is ["YYZ", "LHR"]

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