Skip to content

Instantly share code, notes, and snippets.

@Qata
Last active April 20, 2018 04:11
Show Gist options
  • Save Qata/d9583d88d1ded80719acb47c334ce9f4 to your computer and use it in GitHub Desktop.
Save Qata/d9583d88d1ded80719acb47c334ce9f4 to your computer and use it in GitHub Desktop.
public extension Dictionary {
/// Returns a dictionary where the keys are the first elements of
/// the tuple and the values are the second elements, grouped in
/// arrays associated with the given key.
///
/// let question = [(1, "Hello"), (2, "How"), (3, "Are"), (1, "You")]
/// let g = Dictionary(grouping: question)
/// // g == [1: ["Hello", "You"], 2: ["How"], 3: ["Are"]]
///
/// - Returns: A dictionary containing the grouped elements of this sequence.
public init<S: Sequence, E>(grouping elements: S) where Value == [E], S.Element == (Key, E) {
self = elements.reduce(into: [:]) { result, element in
let (key, value) = element
result[key, default: []] += [value]
}
}
/// Returns a dictionary where the keys are the groupings returned by
/// the given closure and the values are arrays of the elements that
/// returned each specific key.
///
/// let question = ["", "Hello", "", "How", "", "Are", "", "You", ""]
/// let g = Dictionary(compactGrouping: question, by: { $0.first })
/// // g == ["H": ["Hello", "How"], "A": ["Are"], "Y": ["You"]]
///
/// - Parameter transform: `transform` accepts an element of this
/// sequence as its parameter and returns a hashable value, or `nil`.
/// - Returns: A dictionary containing the grouped elements of this sequence, dropping those whose `by` returned `nil`.
public init<S: Sequence, E>(compactGrouping elements: S, by transform: (E) throws -> Key?) rethrows where Value == [E], S.Element == E {
self.init(grouping: try elements.compactMap { value -> (Key, E)? in
guard let transformed = try transform(value) else { return nil }
return (transformed, value)
})
}
/// Returns the first non-`nil` value for a `Sequence` of keys.
///
/// - Parameter keys: A `Sequence` of keys.
/// - Returns: The first non-`nil` value encountered, or `nil`.
public subscript<S: Sequence>(first keys: S) -> Value? where S.Element == Key {
return keys
.first(where: self.keys.contains)
.flatMap { self[$0] }
}
public func mapKeys<T: Hashable>(_ transform: (Key) throws -> T, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows -> [T: Value] {
return try .init(map {
(try transform($0.key), $0.value)
}, uniquingKeysWith: combine)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment