Swift 3 - 扩展一个字典类型为<String, Any>的数组

3

我有一个字典数组:

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'非泛型

我该怎么做才能修复这个错误呢?

使用for value in self来迭代Array是正确的吗?

谢谢

3个回答

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

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

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

最好的,


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接