Stores the elements of a sequence as the values of a Dictionary, keyed by the result of the given closure.
let fruits = ["Apricot", "Banana", "Apple", "Cherry", "Blackberry", "Avocado", "Coconut"]
let fruitByLetter = fruits.keyed(by: { $0.first! })
// Results in:
// [
// "A": "Avocado",
// "B": "Blackberry",
// "C": "Coconut",
// ]
On a key-collision, the latest element is kept by default. Alternatively, you can provide a closure which specifies which value to keep:
let fruits = ["Apricot", "Banana", "Apple", "Cherry", "Blackberry", "Avocado", "Coconut"]
let fruitsByLetter = fruits.keyed(
by: { $0.first! },
resolvingConflictsWith: { key, old, new in old } // Always pick the first fruit
)
// Results in:
// [
// "A": "Apricot",
// "B": "Banana",
// "C": "Cherry",
// ]
The keyed(by:)
and keyed(by:resolvingConflictsWith:)
methods are declared in an Sequence
extension, both returning [Key: Element]
.
extension Sequence {
public func keyed<Key>(
by keyForValue: (Element) throws -> Key
) rethrows -> [Key: Element]
public func keyed<Key>(
by keyForValue: (Element) throws -> Key,
resolvingConflictsWith resolve: ((Key, Element, Element) throws -> Element)? = nil
) rethrows -> [Key: Element]
}
Calling keyed(by:)
is an O(n) operation.
Language | "Keying" API |
---|---|
Java | toMap |
Kotlin | associatedBy |
C# | ToDictionary |
Ruby (ActiveSupport) | index_by |
PHP (Laravel) | keyBy |
- Java's
toMap
is referring toMap
/HashMap
, their naming for Dictionaries and other associative collections. It's easy to confuse with the transformation function,Sequence.map(_:)
. - C#'s
toXXX()
naming doesn't suite Swift well, which tends to preferFoo.init
overtoFoo()
methods. - Ruby's
index_by
naming doesn't fit Swift well, where "index" is a specific term (e.g. theassociatedtype Index
onCollection
). There is also aindex(by:)
method in swift-algorithms, is specifically to do with matching elements up with their indices, and not any arbitrary derived value.
Kotlin's associatedBy
naming is a good alternative, and matches the past tense of Swift's API Design Guidelines, though perhaps we'd spell it associated(by:)
.
Java and C# are interesting in that they provide overloads that let you customize the type of the outermost collection. E.g. using an OrderedDictionary
instead of the default (hashed, unordered) Dictionary
.