Home > other >  Dictionary.merging()... Can closure do per key selection? And, why is API declaration so different f
Dictionary.merging()... Can closure do per key selection? And, why is API declaration so different f

Time:03-12

I'm trying to figure out how to use the Swift Dictionary 'merging' function. I'm confused by the documentation, and I'd like some help understanding how to read that.

https://developer.apple.com/documentation/swift/dictionary/3127173-merging

In the documentation, the API declaration looks like this:

func merging(_ other: [Key : Value], uniquingKeysWith 
   combine: (Value, Value) throws -> Value) rethrows -> [Key : Value]

It explicitly shows that the closure has a label 'uniquingKeysWith`, yet, the documented example doesn't refer to that closure argument label at all! In fact the example seems to ignore a lot of the API declaration (such as return values).

let dictionary = ["a": 1, "b": 2]
let otherDictionary = ["a": 3, "b": 4]

let keepingCurrent = dictionary.merging(otherDictionary)
      { (current, _) in current }
// ["b": 2, "a": 1]
let replacingCurrent = dictionary.merging(otherDictionary)
      { (_, new) in new }
// ["b": 4, "a": 3]

I'd like to do per-key processing in the closure, the example doesn't suggest ist's possible. Specifically, I want to drop nil values in otherDictionary, and override dictionary values with non-nil values.

I suppose I want to filter, and could actually filter() otherDictionary to drop keys with nil values before handing KVPs to the merge function, but I'd rather just do it in one closure if possible.

CodePudding user response:

The documentation is pretty clear. It says

… the combine closure is called with the current and new values for any duplicate keys that are encountered.

Only the keys which occur in both dictionaries are being processed in the closure.

In this example the closure is called for the keys a and b and the higher value of current (representing dictionary) and new (representing otherDictionary) is returned respectively.

let dictionary = ["a": 1, "b": 4, "c": 4]
let otherDictionary = ["a": 3, "b": 2, "d": 5]

let keepingHighest = dictionary.merging(otherDictionary)
{ (current, new) in
    print(current, new) // prints 4 2 and 1 3
    return max(current, new)
}

// ["c": 4, "b": 4, "d": 5, "a": 3]

nil values in a dictionary are fighting the system as according to the definition a nil value indicates a missing key.

  • Related