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

时间:2017-08-02 09:27:44

标签: swift dictionary generics swift3

我正在寻找类型安全的通用版this answer

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

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

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

修改

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

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

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

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

1 个答案:

答案 0 :(得分:10)

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

let filtered = dict.compactMapValues { $0 }

更新:从 Swift 4 开始,您可以轻松完成

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

如果Dictionary应该获得currently being discussed 一种compactMapValues方法,它结合了filtermapValues

上一个回答:) 您可以使用与How can I write a function that will unwrap a generic property in swift assuming it is an optional type?Creating an extension to filter nils from an Array in Swift相同的“技巧”: 定义所有选项符合的协议:

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

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

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

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
    }
}

示例:

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"]