Last active
July 31, 2022 19:29
-
-
Save ollieatkinson/e8957b1f42cb1eaf0d8364ec654bc034 to your computer and use it in GitHub Desktop.
DeepMerge and DeepMerge for Dictionary's in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public struct DeepMapOptions: OptionSet { | |
public let rawValue: UInt | |
public init(rawValue: UInt) { self.rawValue = rawValue } | |
public static let mappingOverArrays = DeepMapOptions(rawValue: 1 << 0) | |
public static let all: DeepMapOptions = [.mappingOverArrays] | |
} | |
extension Dictionary where Value == Any { | |
public func deepMerging( | |
_ other: Self, | |
uniquingKeysWith policy: (Value, Value) -> Value | |
) -> Self { | |
merging(other) { old, new in | |
if let old = old as? Self, let new = new as? Self { | |
return old.deepMerging(new, uniquingKeysWith: policy) | |
} else { | |
return policy(old, new) | |
} | |
} | |
} | |
public func deepMap( | |
_ options: DeepMapOptions = [.mappingOverArrays], | |
_ transform: (Key, Value) throws -> (Key, Value) | |
) rethrows -> Self { | |
try reduce(into: [Key: Value](minimumCapacity: count)) { dictionary, next in | |
let (key, value) = try transform(next.key, next.value) | |
switch value { | |
case let o as Self: | |
dictionary[key] = try o.deepMap(options, transform) | |
case let o as [Self] where options.contains(.mappingOverArrays): | |
dictionary[key] = try o.map { try $0.deepMap(options, transform) } | |
default: | |
dictionary[key] = value | |
} | |
} | |
} | |
public func deepMapAndMerge( | |
_ options: DeepMapOptions = [.mappingOverArrays], | |
_ transform: (Key, Value) throws -> (Key, Value), | |
uniquingKeysWith policy: (Value, Value) -> Value = { $1 } | |
) rethrows -> Self { | |
try reduce(into: [Key: Value](minimumCapacity: count)) { dictionary, next in | |
let (key, value) = try transform(next.key, next.value) | |
switch value { | |
case let o as Self: | |
let mapped = try o.deepMapAndMerge(options, transform, uniquingKeysWith: policy) | |
if let x = dictionary[key] as? Self { | |
dictionary[key] = x.deepMerging(mapped, uniquingKeysWith: policy) | |
} else { | |
dictionary[key] = mapped | |
} | |
case let o as [Self] where options.contains(.mappingOverArrays): | |
dictionary[key] = try o.map { | |
try $0.deepMapAndMerge(options, transform, uniquingKeysWith: policy) | |
} | |
default: | |
dictionary[key] = value | |
} | |
} | |
} | |
} |
Author
ollieatkinson
commented
Jul 30, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment