Guides/Keyed.md
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 |
toMap is referring to Map/HashMap, their naming for Dictionaries and other associative collections. It's easy to confuse with the transformation function, Sequence.map(_:).toXXX() naming doesn't suite Swift well, which tends to prefer Foo.init over toFoo() methods.index_by naming doesn't fit Swift well, where "index" is a specific term (e.g. the associatedtype Index on Collection). There is also a index(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.