convert [(key: String, value: String)] in [String:String] - swift

I want convert [(key: String, value: String)] in [String:String] is possible to do ? If yes how i make ? thanks
var KeyValuePair: [(key: String, value: String)] = [(key: "2017 01 04", value: "143.65"), (key: "2017 01 05", value: "140.78"), (key: "2017 01 06", value: "150.23")]
in
var dictionary: [String:String] = ["2017 01 04":"143.65", "2017 01 05":"140.78", "2017 01 06":"150.23"]

You just need to iterate through the array of tuples and set the key-value pair of your dictionary with the values of the tuple.
var keyValuePairs: [(key: String, value: String)] = [(key: "2017 01 04", value: "143.65"), (key: "2017 01 05", value: "140.78"), (key: "2017 01 06", value: "150.23")]
var dictionary = [String:String]()
keyValuePairs.forEach{
dictionary[$0.0] = $0.1
//since you have named tuples, you could also write dictionary[$0.key] = $0.value
}
print(dictionary)
Please make sure you conform to the Swift naming convention, which is lower-camelcase for variable names.

Swift 4:
If you are sure the the keys are unique, you can use Dictionary.init(uniqueKeysWithValues:):
let dict = Dictionary(uniqueKeysWithValues: keyValuePairs)
Otherwise, you can use Dictionary.init(_:uniquingKeysWith:) instead, which allows you to specify how to handle collisions.
let dict = Dictionary(keyValuePairs, uniquingKeysWith: { previous, new in
return new //always takes the newest value for a given key
})

The one line functional approach would be:
let dictionary = keyValuePair.reduce([String : String]())
{ acc, item in
var output = acc
output.updateValue(item.value, forKey: item.key)
return output
}
You could also neaten things up by implementing an extension to Dictionary
extension Dictionary
{
func appending(value: Value, key: Key) -> Dictionary
{
var mutable = self
mutable.updateValue(value, forKey: key)
return mutable
}
}
let dictionary = keyValuePair.reduce([String : String]()) { $0.appending(value: $1.value, key: $1.key) }

Related

Initializing a Dictionary(uniqueKeysWithValues:) from KeyValuePairs

struct Data {
let storage: [String: Int]
init(_ pairs: KeyValuePairs<String, Int>) {
storage = Dictionary(uniqueKeysWithValues: pairs)
}
}
Compilation error:
Initializer 'init(uniqueKeysWithValues:)' requires the types
'KeyValuePairs<String, Int>.Element' (aka '(key: String, value: Int)')
and '(String, Int)' be equivalent
What can be more natural than to initialize Dictionary(uniqueKeysWithValues:) with KeyValuePairs!? It's just ridiculous that it's impossible to do straightforwardly!
requires '(key: String, value: Int)' and '(String, Int)' be equivalent they are equivalent!
It's because KeyValuePairs.Element has labels.
type(of: (key: "", value: 0)) == type(of: ("", 0)) // false
You need another overload or just an in-place removal of the labels.
public extension Dictionary {
/// Creates a new dictionary from the key-value pairs in the given sequence.
///
/// - Parameter keysAndValues: A sequence of key-value pairs to use for
/// the new dictionary. Every key in `keysAndValues` must be unique.
/// - Returns: A new dictionary initialized with the elements of
/// `keysAndValues`.
/// - Precondition: The sequence must not have duplicate keys.
#inlinable init<Elements: Sequence>(uniqueKeysWithValues keysAndValues: Elements)
where Elements.Element == Element {
self.init(
uniqueKeysWithValues: keysAndValues.map { ($0, $1) }
)
}
}
XCTAssertEqual(
Dictionary(
uniqueKeysWithValues: ["🍐": "🪂", "👯‍♀️": "👯‍♂️"] as KeyValuePairs
),
.init(
uniqueKeysWithValues: [("🍐", "🪂"), ("👯‍♀️", "👯‍♂️")]
)
)
Since Swift is not supporting Splatting (yet), this is how you can achieve it:
struct Data {
let storage: [String: Int]
init(_ pairs: KeyValuePairs<String, Int>) {
storage = Dictionary(uniqueKeysWithValues: pairs.reduce(into: [String: Int]()) { $0[$1.0] = $1.1 } .map { $0 })
}
}
Usages:
let data = Data(KeyValuePairs(dictionaryLiteral: ("a", 1), ("b", 2)))
You may also use reduce:
storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $1.value }
This will work even if you have duplicate keys in pairs (currently it takes the last item from duplicates:
let data = Data(["a": 1, "b": 2, "a": 3] as KeyValuePairs)
print(data.storage)
// ["a": 3, "b": 2]
If you need it to take the first item you can do:
storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $0[$1.key] ?? $1.value }
(or shorter)
storage = pairs.reduce(into: [String: Int]()) { $0[$1.0] = $0[$1.0] ?? $1.1 }
This prints:
let data = Data(["a": 1, "b": 2, "a": 3] as KeyValuePairs)
print(data.storage)
// ["a": 1, "b": 2]
• Fix:
storage = Dictionary(uniqueKeysWithValues: Array(pairs))
• Why:
The method you are trying to use is:
public init<S>(uniqueKeysWithValues keysAndValues: S) where S : Sequence, S.Element == (Key, Value)
And it's missing the S.Element == (Key, Value) compliance.
• A little further:
Note that if you have duplicate keys, you'll have an error. You can use then:
storage = Dictionary(Array(paris)) { _, new in
return new //if you want to keep the last "key" value, or the reverse
}
• Other possibilities :
convert [(key: String, value: String)] in [String:String]

How to convert Array to Dictionary while keeping the same order Swift

Hey I have been looking at some really good question on here. About how to convert a Array to a dictionary but the problem is that is doesn't keep the same order Example:
list = ["test", "test2", "test3"]
outPut:
listNewFromExt = ["test": "test","test3": "test3", "test2": "test2"]
Basically test3 is being switched places with test2
Code:
let listNewFromExt = list.toDictionary{($0, $0)}
extension Sequence {
public func toDictionary<K: Hashable, V>(_ selector: (Iterator.Element) throws -> (K, V)?) rethrows -> [K: V] {
var dict = [K: V]()
for element in self {
if let (key, value) = try selector(element) {
dict[key] = value
}
}
return dict
}
}
Also if you could tell me how to just make the .values "nil" instead of a copy of the key that would be great lol.
In Swift, a Dictionary is an unordered collection by design. Therefore you can't keep any order to it after migrating from an Array.
If you want your values to be nil, just use
let dict = Dictionary<Int, Any?>(uniqueKeysWithValues: [1, 2, 3].map { ($0, nil) })
This evaluates to [2: nil, 3: nil, 1: nil]
If you want some sort of sorting (no pun intended), you may convert the dict to a sorted tuple array:
let sortedTupleArray = dict.sorted { $0.key > $1.key }
This evaluates to [(key: 3, value: nil), (key: 2, value: nil), (key: 1, value: nil)]

How do I compare two dictionaries in Swift?

Is there an easy way to compare two [String: AnyObject] dictionaries in swift, since it doesn't accept the == operator?
By comparing two dictionaries, I mean checking that they have the same exact keys and for every key they have the same values.
As already mentioned by Hot Licks you can use NSDictionary method isEqualToDictionary() to check if they are equal as follow:
let dic1: [String: AnyObject] = ["key1": 100, "key2": 200]
let dic2: [String: AnyObject] = ["key1": 100, "key2": 200]
let dic3: [String: AnyObject] = ["key1": 100, "key2": 250]
println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic2) ) // true
println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic3) ) // false
you can also implement a custom operator "==" as follow:
public func ==(lhs: [String: AnyObject], rhs: [String: AnyObject] ) -> Bool {
return NSDictionary(dictionary: lhs).isEqualToDictionary(rhs)
}
println(dic1 == dic2) // true
println(dic1 == dic3) // false
Xcode 9 • Swift 4
From the docs, dictionary is now defined as a struct:
struct Dictionary<Key : Hashable, Value> : Collection, ExpressibleByDictionaryLiteral
Description
A collection whose elements are key-value pairs. A
dictionary is a type of hash table, providing fast access to the
entries it contains. Each entry in the table is identified using its
key, which is a hashable type such as a string or number. You use that
key to retrieve the corresponding value, which can be any object. In
other languages, similar data types are known as hashes or associated
arrays. Create a new dictionary by using a dictionary literal. A
dictionary literal is a comma-separated list of key-value pairs, in
which a colon separates each key from its associated value, surrounded
by square brackets. You can assign a dictionary literal to a variable
or constant or pass it to a function that expects a dictionary.
Here’s how you would create a dictionary of HTTP response codes and their related messages:
var responseMessages = [200: "OK",
403: "Access forbidden",
404: "File not found",
500: "Internal server error"]
The responseMessages variable is inferred to have type [Int: String].
The Key type of the dictionary is Int, and the Value type of the
dictionary is String.
To create a dictionary with no key-value pairs, use an empty dictionary literal ([:]).
var emptyDict: [String: String] = [:]
Any type that conforms to the Hashable protocol can be used as a dictionary’s Key type, including all of Swift’s basic types. You can use your own custom types as dictionary keys by making them conform to the Hashable protocol.
We don't need to define a custom operator anymore:
From the docs:
static func ==(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
Testing:
let dic1 = ["key1": 100, "key2": 200]
let dic2 = ["key1": 100, "key2": 200]
let dic3 = ["key1": 100, "key2": 250]
print(dic1 == dic2) // true
print(dic1 == dic3) // false
In the example above all dictionary keys and values are the same type.
If we try to compare two dictionaries of type [String: Any] Xcode will complain that Binary operator == cannot be applied to two [String: Any] operands.
let dic4: [String: Any] = ["key1": 100, "key2": "200"]
let dic5: [String: Any] = ["key1": 100, "key2": "200"]
let dic6: [String: Any] = ["key1": 100, "key2": Date()]
print(dic4 == dic5) // Binary operator == cannot be applied to two `[String: Any]` operands
But we can extend the == operator functionality implementing an infix operator, casting Swift Dictionary to NSDictionary and constraining the dictionary values to Hashable Protocol:
Xcode 11 • Swift 5.1
public func ==<K, L: Hashable, R: Hashable>(lhs: [K: L], rhs: [K: R] ) -> Bool {
(lhs as NSDictionary).isEqual(to: rhs)
}
Testing:
let dic4: [String: AnyHashable] = ["key1": 100, "key2": "200"]
let dic5: [String: AnyHashable] = ["key1": 100, "key2": "200"]
let dic6: [String: AnyHashable] = ["key1": 100, "key2": Date()]
print(dic4 == dic5) // true
print(dic4 == dic6) // false
let dic7: [String: String] = [ "key2": "200"]
let dic8: [String: Date] = [ "key2": Date()]
print(dic7 == dic8) // false
Swift 4 Update:
Comparing Dictionaries is now native! (Docs here)
Swift 3:
Leo Dabus already has an excellently written post with the accepted solution. However, for me, I found that it needed one more step to be fully usable. As you can see from his code, you need to set your dictionary type to [AnyHashable: Any], or otherwise you'll get Binary operator '==' cannot be applied to two '[String : Any]' operands, to use a dictionary common in deserializing JSON for my example.
Generics to the rescue!:
// Swift 3.0
func == <K, V>(left: [K:V], right: [K:V]) -> Bool {
return NSDictionary(dictionary: left).isEqual(to: right)
}
or in another case I had, with [String: Any?]:
func == <K, V>(left: [K:V?], right: [K:V?]) -> Bool {
guard let left = left as? [K: V], let right = right as? [K: V] else { return false }
return NSDictionary(dictionary: left).isEqual(to: right)
}
In Swift 2, when both Key and Value are Equatable, you can use == on the dictionary itself:
public func ==<Key : Equatable, Value : Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
And, NSObject is Equatable:
public func ==(lhs: NSObject, rhs: NSObject) -> Bool
In your case, if you are working with Obj-C objects that you want to compare using isEqual:, you can simply use NSObject as your value type (rather than AnyObject).
Without custom type in value of Dictionary, in Swift 2+ you can use the == operator to compare two Dictionary to check if they are equal or not.
But in some cases with custom types as the Dictionary's value (like struct), you must adopt Equatable in order for that custom type to use == operator.
Ex:
// custom type
struct Custom: Equatable {
var value: Int
}
// MARK: adopting Equatable
func ==(lhs: Custom, rhs: Custom) -> Bool {
if lhs.value == rhs.value {
return true
} else {
return false
}
}
Now you can use the == operator to compare two dictionaries:
let dic3: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)]
let dic4: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)]
if (dic3 == dic4) {
print("equal")
} else {
print("not equal")
}

Swift dictionary comprehension

Other languages such as Python let you use a dictionary comprehension to make a dict from an array, but I haven't figure out how to do this in Swift. I thought I could use something like this but it doesn't compile:
let x = ["a","b","c"]
let y = x.map( { ($0:"x") })
// expected y to be ["a":"x", "b":"x", "c":"x"]
What is the correct way to generate a dictionary from an array in swift?
The map method simply transforms each element of an array into a new element. The result is, however, still an array. To transform the array into a dictionary you can use the reduce method.
let x = ["a","b","c"]
let y = x.reduce([String: String]()) { (var dict, arrayElem) in
dict[arrayElem] = "this is the value for \(arrayElem)"
return dict
}
This will generate the dictionary
["a": "this is the value for a",
"b": "this is the value for b",
"c": "this is the value for c"]
Some explanation: The first argument of reduce is the initial value which in this case is the empty dictionary [String: String](). The second argument of reduce is a callback for combining each element of the array into the current value. In this case, the current value is the dictionary and we define a new key and value in it for every array element. The modified dictionary also needs to be returned in the callback.
Update: Since the reduce approach can be heavy on memory for large arrays (see comments) you could also define a custom comprehension function similar to the below snippet.
func dictionaryComprehension<T,K,V>(array: [T], map: (T) -> (key: K, value: V)?) -> [K: V] {
var dict = [K: V]()
for element in array {
if let (key, value) = map(element) {
dict[key] = value
}
}
return dict
}
Calling that function would look like this.
let x = ["a","b","c"]
let y = dictionaryComprehension(x) { (element) -> (key: String, value: String)? in
return (key: element, value: "this is the value for \(element)")
}
Update 2: Instead of a custom function you could also define an extension on Array which would make the code easier to reuse.
extension Array {
func toDict<K,V>(map: (T) -> (key: K, value: V)?) -> [K: V] {
var dict = [K: V]()
for element in self {
if let (key, value) = map(element) {
dict[key] = value
}
}
return dict
}
}
Calling the above would look like this.
let x = ["a","b","c"]
let y = x.toDict { (element) -> (key: String, value: String)? in
return (key: element, value: "this is the value for \(element)")
}

What's the cleanest way of applying map() to a dictionary in Swift?

I'd like to map a function on all keys in the dictionary. I was hoping something like the following would work, but filter cannot be applied to dictionary directly. What's the cleanest way of achieving this?
In this example, I'm trying to increment each value by 1. However this is incidental for the example - the main purpose is to figure out how to apply map() to a dictionary.
var d = ["foo" : 1, "bar" : 2]
d.map() {
$0.1 += 1
}
Swift 4+
Good news! Swift 4 includes a mapValues(_:) method which constructs a copy of a dictionary with the same keys, but different values. It also includes a filter(_:) overload which returns a Dictionary, and init(uniqueKeysWithValues:) and init(_:uniquingKeysWith:) initializers to create a Dictionary from an arbitrary sequence of tuples. That means that, if you want to change both the keys and values, you can say something like:
let newDict = Dictionary(uniqueKeysWithValues:
oldDict.map { key, value in (key.uppercased(), value.lowercased()) })
There are also new APIs for merging dictionaries together, substituting a default value for missing elements, grouping values (converting a collection into a dictionary of arrays, keyed by the result of mapping the collection over some function), and more.
During discussion of the proposal, SE-0165, that introduced these features, I brought up this Stack Overflow answer several times, and I think the sheer number of upvotes helped demonstrate the demand. So thanks for your help making Swift better!
With Swift 5, you can use one of the five following snippets in order to solve your problem.
#1. Using Dictionary mapValues(_:) method
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
let newDictionary = dictionary.mapValues { value in
return value + 1
}
//let newDictionary = dictionary.mapValues { $0 + 1 } // also works
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
#2. Using Dictionary map method and init(uniqueKeysWithValues:) initializer
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
let tupleArray = dictionary.map { (key: String, value: Int) in
return (key, value + 1)
}
//let tupleArray = dictionary.map { ($0, $1 + 1) } // also works
let newDictionary = Dictionary(uniqueKeysWithValues: tupleArray)
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
#3. Using Dictionary reduce(_:_:) method or reduce(into:_:) method
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
let newDictionary = dictionary.reduce([:]) { (partialResult: [String: Int], tuple: (key: String, value: Int)) in
var result = partialResult
result[tuple.key] = tuple.value + 1
return result
}
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
let newDictionary = dictionary.reduce(into: [:]) { (result: inout [String: Int], tuple: (key: String, value: Int)) in
result[tuple.key] = tuple.value + 1
}
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
#4. Using Dictionary subscript(_:default:) subscript
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
var newDictionary = [String: Int]()
for (key, value) in dictionary {
newDictionary[key, default: value] += 1
}
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
#5. Using Dictionary subscript(_:) subscript
let dictionary = ["foo": 1, "bar": 2, "baz": 5]
var newDictionary = [String: Int]()
for (key, value) in dictionary {
newDictionary[key] = value + 1
}
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
While most of the answers here focus on how to map the entire dictionary (keys and values), the question really only wanted to map the values. This is an important distinction since mapping values allows you to guarantee the same number of entries, whereas mapping both key and value might result in duplicate keys.
Here’s an extension, mapValues, that allows you to map just the values. Note it also extends dictionary with an init from a sequence of key/value pairs, which is a bit more general than initializing it from an array:
extension Dictionary {
init<S: SequenceType where S.Generator.Element == Element>
(_ seq: S) {
self.init()
for (k,v) in seq {
self[k] = v
}
}
func mapValues<T>(transform: Value->T) -> Dictionary<Key,T> {
return Dictionary<Key,T>(zip(self.keys, self.values.map(transform)))
}
}
The cleanest way is to just add map to Dictionary:
extension Dictionary {
mutating func map(transform: (key:KeyType, value:ValueType) -> (newValue:ValueType)) {
for key in self.keys {
var newValue = transform(key: key, value: self[key]!)
self.updateValue(newValue, forKey: key)
}
}
}
Checking that it works:
var dic = ["a": 50, "b": 60, "c": 70]
dic.map { $0.1 + 1 }
println(dic)
dic.map { (key, value) in
if key == "a" {
return value
} else {
return value * 2
}
}
println(dic)
Output:
[c: 71, a: 51, b: 61]
[c: 142, a: 51, b: 122]
You can also use reduce instead of map. reduce is capable of doing anything map can do and more!
let oldDict = ["old1": 1, "old2":2]
let newDict = reduce(oldDict, [String:Int]()) { dict, pair in
var d = dict
d["new\(pair.1)"] = pair.1
return d
}
println(newDict) // ["new1": 1, "new2": 2]
It would be fairly easy to wrap this in an extension, but even without the extension it lets you do what you want with one function call.
Swift 5
map function of dictionary comes with this syntax.
dictData.map(transform: ((key: String, value: String)) throws -> T)
you can just set closure values to this
var dictData: [String: String] = [
"key_1": "test 1",
"key_2": "test 2",
"key_3": "test 3",
"key_4": "test 4",
"key_5": "test 5",
]
dictData.map { (key, value) in
// Operations on values or key
}
It may be give this warning Result of call to 'map' is unused
Then just set _ = before variable.
May be it will help you
Thank you.
It turns out you can do this. What you have to do is create an array from the MapCollectionView<Dictionary<KeyType, ValueType>, KeyType> returned from the dictionaries keys method. (Info here) You can then map this array, and pass the updated values back to the dictionary.
var dictionary = ["foo" : 1, "bar" : 2]
Array(dictionary.keys).map() {
dictionary.updateValue(dictionary[$0]! + 1, forKey: $0)
}
dictionary
I was looking for a way to map a dictionary right into a typed Array with custom objects. Found the solution in this extension:
extension Dictionary {
func mapKeys<U> (transform: Key -> U) -> Array<U> {
var results: Array<U> = []
for k in self.keys {
results.append(transform(k))
}
return results
}
func mapValues<U> (transform: Value -> U) -> Array<U> {
var results: Array<U> = []
for v in self.values {
results.append(transform(v))
}
return results
}
func map<U> (transform: Value -> U) -> Array<U> {
return self.mapValues(transform)
}
func map<U> (transform: (Key, Value) -> U) -> Array<U> {
var results: Array<U> = []
for k in self.keys {
results.append(transform(k as Key, self[ k ]! as Value))
}
return results
}
func map<K: Hashable, V> (transform: (Key, Value) -> (K, V)) -> Dictionary<K, V> {
var results: Dictionary<K, V> = [:]
for k in self.keys {
if let value = self[ k ] {
let (u, w) = transform(k, value)
results.updateValue(w, forKey: u)
}
}
return results
}
}
Using it as followed:
self.values = values.map({ (key:String, value:NSNumber) -> VDLFilterValue in
return VDLFilterValue(name: key, amount: value)
})
Swift 3
I try an easy way in Swift 3.
I want to map [String: String?] to [String : String], I use forEach instead of map or flat map.
let oldDict = ["key0": "val0", "key1": nil, "key1": "val2","key2": nil]
var newDict = [String: String]()
oldDict.forEach { (source: (key: String, value: String?)) in
if let value = source.value{
newDict[source.key] = value
}
}
According to the Swift Standard Library Reference, map is a function of arrays. Not for dictionaries.
But you could iterate your dictionary to modify the keys:
var d = ["foo" : 1, "bar" : 2]
for (name, key) in d {
d[name] = d[name]! + 1
}
I you're only trying to map the values (potentially changing their type), include this extension:
extension Dictionary {
func valuesMapped<T>(_ transform: (Value) -> T) -> [Key: T] {
var newDict = [Key: T]()
for (key, value) in self {
newDict[key] = transform(value)
}
return newDict
}
}
Given you have this dictionary:
let intsDict = ["One": 1, "Two": 2, "Three": 3]
Single-line value transformation then looks like this:
let stringsDict = intsDict.valuesMapped { String($0 * 2) }
// => ["One": "2", "Three": "6", "Two": "4"]
Multi-line value transformation then looks like this:
let complexStringsDict = intsDict.valuesMapped { (value: Int) -> String in
let calculationResult = (value * 3 + 7) % 5
return String("Complex number #\(calculationResult)")
}
// => ["One": "Complex number #0", "Three": ...
Another approach is to map to a dictionary and reduce, where functions keyTransform and valueTransform are functions.
let dictionary = ["a": 1, "b": 2, "c": 3]
func keyTransform(key: String) -> Int {
return Int(key.unicodeScalars.first!.value)
}
func valueTransform(value: Int) -> String {
return String(value)
}
dictionary.map { (key, value) in
[keyTransform(key): valueTransform(value)]
}.reduce([Int:String]()) { memo, element in
var m = memo
for (k, v) in element {
m.updateValue(v, forKey: k)
}
return m
}
Swift 3 I used this,
func mapDict(dict:[String:Any])->[String:String]{
var updatedDict:[String:String] = [:]
for key in dict.keys{
if let value = dict[key]{
updatedDict[key] = String(describing: value)
}
}
return updatedDict
}
Usage:
let dict:[String:Any] = ["MyKey":1]
let mappedDict:[String:String] = mapDict(dict: dict)
Ref
Swift 3
Usage:
let value = ["a": "AAA", "b": "BBB", "c": "CCC"]
value.transformed { ($1, $0) } // ["BBB": "b", "CCC": "c", "AAA": "a"]
Extension:
extension Dictionary {
func transformed(closure: (Key, Value) -> (Key, Value)?) -> [Key: Value] {
var dict = [Key: Value]()
for key in keys {
guard
let value = self[key],
let keyValue = closure(key, value)
else { continue }
dict[keyValue.0] = keyValue.1
}
return dict
}
}