add additional dictionary convenience functions for transformations

This commit is contained in:
Kyle Matthew Hedden 2022-07-22 15:52:17 -04:00
parent 9bb56d09db
commit a0f2111a51

View File

@ -192,6 +192,61 @@ public extension Dictionary {
return previousObject
}
/// Transforms dictionary keys without modifying values.
/// Deduplicates transformed keys.
///
/// Example:
/// ```
/// ["one": 1, "two": 2, "three": 3, "": 4].mapKeys({ $0.first }, uniquingKeysWith: { max($0, $1) })
/// // [Optional("o"): 1, Optional("t"): 3, nil: 4]
/// ```
///
/// - Parameters:
/// - transform: A closure that accepts each key of the dictionary as
/// its parameter and returns a transformed key of the same or of a different type.
/// - combine:A closure that is called with the values for any duplicate
/// keys that are encountered. The closure returns the desired value for
/// the final dictionary.
/// - Returns: A dictionary containing the transformed keys and values of this dictionary.
func mapKeys<T>(_ transform: (Key) throws -> T, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows -> [T: Value] {
try .init(map { (try transform($0.key), $0.value) }, uniquingKeysWith: combine)
}
/// Transforms dictionary keys without modifying values.
/// Drops (key, value) pairs where the transform results in a nil key.
/// Deduplicates transformed keys.
///
/// Example:
/// ```
/// ["one": 1, "two": 2, "three": 3, "": 4].compactMapKeys({ $0.first }, uniquingKeysWith: { max($0, $1) })
/// // ["o": 1, "t": 3]
/// ```
///
/// - Parameters:
/// - transform: A closure that accepts each key of the dictionary as
/// its parameter and returns an optional transformed key of the same or of a different type.
/// - combine: A closure that is called with the values for any duplicate
/// keys that are encountered. The closure returns the desired value for
/// the final dictionary.
/// - Returns: A dictionary containing the non-nil transformed keys and values of this dictionary.
func compactMapKeys<T>(_ transform: (Key) throws -> T?, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows -> [T: Value] {
try .init(compactMap { (try transform($0.key), $0.value) as? (T, Value) }, uniquingKeysWith: combine)
}
/// Unconditionally merge another dictionary into this one with preference to the incoming keys.
func mergingLeft(_ other: Self) -> Self {
return merging(other) { first, second in
second
}
}
/// Unconditionally merge this dictionary into another with preference to the existing keys.
func mergingRight(_ other: Self) -> Self {
return merging(other) { first, second in
first
}
}
}
public extension Optional where Wrapped == Dictionary<AnyHashable, Any> {