用于零过滤的通用Swift字典扩展

Xav*_*ler 3 generics dictionary swift swift3

我正在寻找这个答案的类型安全,通用版本.

这是我正在寻找的方法签名:

extension Dictionary where Value == Optional<T> {
    func filterNil() -> <Key, T>
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在Swift 3中表达这个?

编辑:

我创建带有可选值的Dictionary的动机是我需要这样的东西:

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

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

我更喜欢字典文字来创建一个空字典并手动填充值.

Mar*_*n R 10

更新:Swift 5开始,这将是:

let filtered = dict.compactMapValues { $0 }
Run Code Online (Sandbox Code Playgroud)

更新:Swift 4开始,你可以做到

let filtered = dict.filter( { $0.value != nil }).mapValues( { $0! })
Run Code Online (Sandbox Code Playgroud)

这是目前正在讨论是否Dictionary应该得到compactMapValues它结合了方法filtermapValues.


(上一个答案:)你可以使用相同的"技巧",如何编写一个函数,在swift中解包一个通用属性,假设它是一个可选类型?创建一个扩展来从Swift中的数组中过滤nils:定义所有选项符合的协议:

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

extension Optional : OptionalType {
    func intoOptional() -> Wrapped? {
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您的字典扩展名可以定义为:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

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"]
Run Code Online (Sandbox Code Playgroud)