Generic Swift Dictionary Extension for nil filteri

2019-02-20 09:40发布

I'm looking for a type safe, generic version of this answer.

This is the method signature I'm looking for:

extension Dictionary where Value == Optional<T> {
    func filterNil() -> <Key, T>
}

Is there any way to express this in Swift 3?

Edit:

My motivation for creating a Dictionary with optional values is that I need something like this:

struct User {
    var mail: String?
    var name: String?

    func marshaled() -> [String: Any] {
        return [
            "mail": mail,
            "name": name
        ].filterNil()
    }
}

I much prefer the dictionary literal to creating an empty dictionary and filling the values manually.

1条回答
做个烂人
2楼-- · 2019-02-20 10:20

Update: As of Swift 4, you can simply do

let filtered = dict.filter( { $0.value != nil }).mapValues( { $0! })

It is currently being discussed if Dictionary should get a compactMapValues method which combines filter and mapValues.


(Previous answer:) You can use the same "trick" as in How can I write a function that will unwrap a generic property in swift assuming it is an optional type? and Creating an extension to filter nils from an Array in Swift: define a protocol to which all optionals conform:

protocol OptionalType {
    associatedtype Wrapped
    func intoOptional() -> Wrapped?
}

extension Optional : OptionalType {
    func intoOptional() -> Wrapped? {
        return self
    }
}

Then your dictionary extension can be defined as:

extension Dictionary where Value: OptionalType {
    func filterNil() -> [Key: Value.Wrapped] {
        var result: [Key: Value.Wrapped] = [:]
        for (key, value) in self {
            if let unwrappedValue = value.intoOptional() {
                result[key] = unwrappedValue
            }
        }
        return result
    }
}

Example:

let dict = ["mail": nil, "name": "John Doe"] // Type is [String : String?]
let filtered = dict.filterNil() // Type is [String : String]
print(filtered) // Output: ["name": "John Doe"]
查看更多
登录 后发表回答