Swift 3 - 扩展Dictionary <string,any =“”>的数组

时间:2016-10-18 12:02:02

标签: arrays dictionary swift3 extend

我有这个词典数组:

var dicts = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]

我应该如何扩展Array以便我有这个功能:

dicts.values(of: "key1") // result: ["value1", "value3"]

我试试这个:

extension Array where Iterator.Element == [String: Any] { // ERROR!

    func values(of key: String) -> [Any]? {
        var result: [Any]?
        for value in self {
            let val = value as! Dictionary<String, Any>
            for k in val.keys {
                if k == key {
                    if result == nil {
                        result = [Any]()
                    }
                    result?.append(val[k])
                    break
                }
            }
        }
        return result
    }
}

但我总是在extension Array声明处标记错误:

  

错误:同类型要求使通用参数'Element'非通用

我该怎么做才能解决此错误?

使用Array迭代for value in self是否正确?

由于

3 个答案:

答案 0 :(得分:6)

extension Sequence where Iterator.Element == [String: Any] {

    func values(of key: String) -> [Any]? {
        var result: [Any] = []
        for value in self {
            let val = value 
            for (k, v) in val {
                if k == key {
                    result.append(v)
                    break
                }
            }
        }
        return result.isEmpty ? nil : result
    }
}

var dicts: [[String: Any]] = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]
dicts.values(of: "key1")   // ["value1", "value3"]

或更短的版本:

extension Sequence where Iterator.Element == [String: Any] {

    func values(of key: String) -> [Any]? {
        let result: [Any] = reduce([]) { (result, dict) -> [Any] in
            var result = result
            result.append(dict.filter{ $0.key == key }.map{ $0.value })
            return result
        }
        return result.isEmpty ? nil : result
    }
}

var dicts: [[String: Any]] = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]
dicts.values(of: "key1")

并且没有减少功能:

extension Sequence where Iterator.Element == [String: Any] {

    func values(of key: String) -> [Any]? {
        var result: [Any] = []
        forEach {
            result.append($0.filter{ $0.key == key }.map{ $0.value })
        }
        return result.isEmpty ? nil : result
    }
}

var dicts: [[String: Any]] = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]
dicts.values(of: "key1")

答案 1 :(得分:3)

使用compactMap(Swift 3中为flatMap)的合并解决方案,用于过滤nil

let dicts : [[String:Any]] = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]

extension Sequence where Iterator.Element == [String:Any] {

  func values(of key: String) -> [Any] {
    return self.compactMap {$0[key]}
  }
}

dicts.values(of:"key1")

答案 2 :(得分:0)

谢谢你,@ JMI,你的解决方案非常优雅。

我想在您的工作中添加更多细节:

extension Sequence where Iterator.Element == [String: Any] {
    func values(of key: String) -> [Any]? {
        var result = [Any]()
        forEach {
            let tmp = $0.filter{$0.key == key}.map{$0.value}
            if tmp.count > 0 {
                result.append(tmp[0])
            }
        }
        return result.isEmpty ? nil : result
    }
}

var dicts: [[String: Any]] = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]

if let result = dicts.values(of: "key1") {
    for element in result {
        print("\(element) -> \(type(of: element))")
    }
}
else {
    print("no result")
}

最佳,