diff --git a/CHANGELOG.md b/CHANGELOG.md index 089fae260..962caa7a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ The changelog for **SwifterSwift**. Also see the [releases](https://github.com/S - `beginRefresh(in tableView:, animated:, sendAction:)` UIRefreshControl extension to begin refresh programatically. [#525](https://github.com/SwifterSwift/SwifterSwift/pull/525) by [ratulSharker](https://github.com/ratulSharker) - **Dictionary**: - Added `removeValueForRandomKey()` to remove a value for a random key from a dictionary. [#497](https://github.com/SwifterSwift/SwifterSwift/pull/497) by [vyax](https://github.com/vyax). + - Added `mapKeysAndValues(_:)` to map a `Dictionary` into a `Dictionary` with different (or same) `Key` and `Value` types. [#546](https://github.com/SwifterSwift/SwifterSwift/pull/546) by [guykogus](https://github.com/guykogus) + - Added `compactMapKeysAndValues(_:)` to map a `Dictionary` into a `Dictionary`, excluding `nil` results, with different (or same) `Key` and `Value` types. [#546](https://github.com/SwifterSwift/SwifterSwift/pull/546) by [guykogus](https://github.com/guykogus) - **RangeReplaceableCollection**: - Added `removeRandomElement()` to remove a random element from a collection. [#497](https://github.com/SwifterSwift/SwifterSwift/pull/497) by [vyax](https://github.com/vyax). - **UIView** diff --git a/Sources/Extensions/SwiftStdlib/DictionaryExtensions.swift b/Sources/Extensions/SwiftStdlib/DictionaryExtensions.swift index 5d4a5fca0..2611f816b 100644 --- a/Sources/Extensions/SwiftStdlib/DictionaryExtensions.swift +++ b/Sources/Extensions/SwiftStdlib/DictionaryExtensions.swift @@ -177,3 +177,20 @@ public extension Dictionary { } } + +extension Dictionary { + /// SwifterSwift: Returns a dictionary containing the results of mapping the given closure over the sequence’s elements. + /// - Parameter transform: A mapping closure. `transform` accepts an element of this sequence as its parameter and returns a transformed value of the same or of a different type. + /// - Returns: A dictionary containing the transformed elements of this sequence. + func mapKeysAndValues(_ transform: ((key: Key, value: Value)) throws -> (K, V)) rethrows -> [K: V] { + return [K: V](uniqueKeysWithValues: try map(transform)) + } + + /// SwifterSwift: Returns a dictionary containing the non-`nil` results of calling the given transformation with each element of this sequence. + /// - Parameter transform: A closure that accepts an element of this sequence as its argument and returns an optional value. + /// - Returns: A dictionary of the non-`nil` results of calling `transform` with each element of the sequence. + /// - Complexity: *O(m + n)*, where _m_ is the length of this sequence and _n_ is the length of the result. + func compactMapKeysAndValues(_ transform: ((key: Key, value: Value)) throws -> (K, V)?) rethrows -> [K: V] { + return [K: V](uniqueKeysWithValues: try compactMap(transform)) + } +} diff --git a/Tests/SwiftStdlibTests/DictionaryExtensionsTests.swift b/Tests/SwiftStdlibTests/DictionaryExtensionsTests.swift index 965a53558..7df5a5d4b 100644 --- a/Tests/SwiftStdlibTests/DictionaryExtensionsTests.swift +++ b/Tests/SwiftStdlibTests/DictionaryExtensionsTests.swift @@ -102,4 +102,36 @@ final class DictionaryExtensionsTests: XCTestCase { XCTAssertFalse(dict.keys.contains("key2")) } + func testMapKeysAndValues() { + let intToString = [0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9"] + + let stringToInt: [String: Int] = intToString.mapKeysAndValues { (key, value) in + return (String(describing: key), Int(value)!) + } + + XCTAssertEqual(stringToInt, ["0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9]) + } + + func testCompactMapKeysAndValues() { + // swiftlint:disable:next nesting + enum IntWord: String { + case zero + case one + case two + } + + let strings = [ + 0: "zero", + 1: "one", + 2: "two", + 3: "three" + ] + let words: [String: IntWord] = strings.compactMapKeysAndValues { (key, value) in + guard let word = IntWord(rawValue: value) else { return nil } + return (String(describing: key), word) + } + + XCTAssertEqual(words, ["0": .zero, "1": .one, "2": .two]) + } + }