Mapping a Dictionary to a Dictionary?


(Daniel Tartaglia) #1

I use the below to do this:

dict2 = dict1.map { $0.withUpdate($0.0, value: $0.1) }

The above will effectively do a straight copy, you will probably want to modify the values passed in though…

https://gist.github.com/dtartaglia/6141e6003e408399c2dd7a7cc266dce6#file-dictionaryextensions-swift

extension Dictionary {

    /// An immutable version of update. Returns a new dictionary containing self's values and the key/value passed in.
    func withUpdate(key: Key, value: Value) -> Dictionary<Key, Value> {
        var result = self
        result[key] = value
        return result
    }
}

···

On Aug 30, 2016, at 1:00 PM, swift-users-request@swift.org wrote:

[swift-users] Mapping a Dictionary to a Dictionary?


(Jens Alfke) #2

I don’t see how this can work. Dictionary.map returns an Array, not a Dictionary.
Also, in the callback function $0 is the key, so your Dictionary.withUpdate method only makes sense if the key type of the Dictionary is another Dictionary, which seems … very unusual.

(To clarify, I wasn’t asking how to accomplish this; it’s pretty simple to write it either as an extension method or as a simple one-off ‘for’ loop. I was just making sure it wasn’t already in the standard library, since it seems an obvious thing to have.)

—Jens

···

On Aug 31, 2016, at 10:51 AM, Daniel Tartaglia <danielt1263@gmail.com> wrote:

I use the below to do this:

dict2 = dict1.map { $0.withUpdate($0.0, value: $0.1) }


(Daniel Tartaglia) #3

Sorry, I was too quick to send that email… Here is something from a playground that works:

extension Dictionary {
  
  /// An immutable version of update. Returns a new dictionary containing self's values and the key/value passed in.
  func withUpdate(key: Key, value: Value) -> Dictionary<Key, Value> {
    var result = self
    result[key] = value
    return result
  }
}

let dict1 = ["joe": 3, "mary": 4]

let dict2 = dict1.reduce([:]) { dict2, element in dict2.withUpdate(element.0, value: element.1 * 5) }

print(dict2)

Remember, map can be implemented in terms of reduce…

···

On Aug 31, 2016, at 2:17 PM, Jens Alfke <jens@mooseyard.com> wrote:

On Aug 31, 2016, at 10:51 AM, Daniel Tartaglia <danielt1263@gmail.com <mailto:danielt1263@gmail.com>> wrote:

I use the below to do this:

dict2 = dict1.map { $0.withUpdate($0.0, value: $0.1) }

I don’t see how this can work. Dictionary.map returns an Array, not a Dictionary.
Also, in the callback function $0 is the key, so your Dictionary.withUpdate method only makes sense if the key type of the Dictionary is another Dictionary, which seems … very unusual.

(To clarify, I wasn’t asking how to accomplish this; it’s pretty simple to write it either as an extension method or as a simple one-off ‘for’ loop. I was just making sure it wasn’t already in the standard library, since it seems an obvious thing to have.)

—Jens


(Jens Alfke) #4

That’s going to be quite slow, like O(n^2), since it copies the dictionary every time it adds a key to it.
It also seems more complicated than the simple for-loop implementation; but then, I’m not a functional-language programmer.

// here’s how I’d do it; not tested in a playground
var dict2 = [Key:Value](minCapacity: dict1.count)
for (k,v) in dict1 {
  let (k1,v1) = xform(k,v)
  dict2[k1] = v1
}

—Jens