A sequence whose elements can be traversed multiple times, nondestructively, and accessed by indexed subscript.
Language
- Swift
Overview
Collections are used extensively throughout the standard library. When you use arrays, dictionaries, views of a string’s contents and other types, you benefit from the operations that the Collection protocol declares and implements.
In addition to the methods that collections inherit from the Sequence protocol, you gain access to methods that depend on accessing an element at a specific position when using a collection.
For example, if you want to print only the first word in a string, search for the index of the first space and then create a subsequence up to that position.
let text = "Buffalo buffalo buffalo buffalo."
if let firstSpace = text.characters.index(of: " ") {
print(String(text.characters.prefix(upTo: firstSpace)))
}
// Prints "Buffalo"
The firstSpace constant is an index into the text.characters collection. firstSpace is the position of the first space in the collection. You can store indices in variables, and pass them to collection algorithms or use them later to access the corresponding element. In the example above, firstSpace is used to extract the prefix that contains elements up to that index.
You can pass only valid indices to collection operations. You can find a complete set of a collection’s valid indices by starting with the collection’s startIndex property and finding every successor up to, and including, the endIndex property. All other values of the Index type, such as the startIndex property of a different collection, are invalid indices for this collection.
Saved indices may become invalid as a result of mutating operations; for more information about index invalidation in mutable collections, see the reference for the MutableCollection and RangeReplaceableCollection protocols, as well as for the specific type you’re using.
Accessing Individual Elements
You can access an element of a collection through its subscript with any valid index except the collection’s endIndex property, a “past the end” index that does not correspond with any element of the collection.
Here’s an example of accessing the first character in a string through its subscript:
let firstChar = text.characters[text.characters.startIndex]
print(firstChar)
// Prints "B"
The Collection protocol declares and provides default implementations for many operations that depend on elements being accessible by their subscript. For example, you can also access the first character of text using the first property, which has the value of the first element of the collection, or nil if the collection is empty.
print(text.characters.first)
// Prints "Optional("B")"
Traversing a Collection
Although a sequence can be consumed as it is traversed, a collection is guaranteed to be multipass: Any element may be repeatedly accessed by saving its index. Moreover, a collection’s indices form a finite range of the positions of the collection’s elements. This guarantees the safety of operations that depend on a sequence being finite, such as checking to see whether a collection contains an element.
Iterating over the elements of a collection by their positions yields the same elements in the same order as iterating over that collection using its iterator. This example demonstrates that the characters view of a string returns the same characters in the same order whether the view’s indices or the view itself is being iterated.
let word = "Swift"
for character in word.characters {
print(character)
}
// Prints "S"
// Prints "w"
// Prints "i"
// Prints "f"
// Prints "t"
for i in word.characters.indices {
print(word.characters[i])
}
// Prints "S"
// Prints "w"
// Prints "i"
// Prints "f"
// Prints "t"
Conforming to the Collection Protocol
If you create a custom sequence that can provide repeated access to its elements, make sure that its type conforms to the Collection protocol in order to give a more useful and more efficient interface for sequence and collection operations. To add Collection conformance to your type, you must declare at least the four following requirements:
the
startIndexandendIndexproperties,a subscript that provides at least read-only access to your type’s elements, and
the
index(after:)method for advancing an index into your collection.
Expected Performance
Types that conform to Collection are expected to provide the startIndex and endIndex properties and subscript access to elements as O(1) operations. Types that are not able to guarantee that expected performance must document the departure, because many collection operations depend on O(1) subscripting performance for their own performance guarantees.
The performance of some collection operations depends on the type of index that the collection provides. For example, a random-access collection, which can measure the distance between two indices in O(1) time, will be able to calculate its count property in O(1) time. Conversely, because a forward or bidirectional collection must traverse the entire collection to count the number of contained elements, accessing its count property is an O(n) operation.