Adithya
Adithya

Reputation: 4705

compactMapValues not filtering nil values

compactMapValues on a dictionary returns dictionary with the nil values.

I am using the method as suggested by most of the documentation out there. compactMapValues { $0 }

extension Dictionary where Key == RequestParameter {

    func nilFiltered() -> [RequestParameter: Any] {
        return compactMapValues { $0 }
    }

}

RequestParameter is a enum and I am calling the method like..

[RequestParameter.param1: "value1", RequestParameter.param2: nil]. nilFiltered()

The necessary filtering is not happening. Is this is a known bug or am I doing something wrong?

Upvotes: 1

Views: 410

Answers (2)

Nikolay Shubenkov
Nikolay Shubenkov

Reputation: 3233

One of solutions is the following:

let dictionary =  (["key1": 1,
                    "key2": nil,
                    "key3": "anotherValue",
                    "key4": nil] as [String: Any?])
                    .compactMapValues { $0 }

print(dictionary)

This will make output:

["key1": 1, "key3": "anotherValue"]

Upvotes: 0

user652038
user652038

Reputation:

If you just return $0, that adds a level of optionality The return value of

[RequestParameter.param1: "value1", .param2: nil]

is a [RequestParameter: String?], which introduces double-optionality. Either do this:

extension Dictionary {
  func nilFiltered<Wrapped>() -> [Key: Any] where Value == Wrapped? {
    compactMapValues { $0 }
  }
}

or if you don't actually need Any, avoid that rubbish!

extension Dictionary {
  func nilFiltered<Wrapped>() -> [Key: Wrapped] where Value == Wrapped? {
    compactMapValues { $0 }
  }
}

Here's an alternative that I don't like.

extension Dictionary {
  func nilFiltered() -> [Key: Any] {
    compactMapValues {
      if case nil as Value? = $0 {
        return nil
      }

      return $0
    }
  }
}

Upvotes: 3

Related Questions