I have this array of dictionaries:
var dicts = [["key1": "value1", "key2": "value2"], ["key1": "value3", "key2": "value4"]]
How should I extend Array
so that I have this function:
dicts.values(of: "key1") // result: ["value1", "value3"]
I try this:
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
}
}
But I always have error marked at extension Array
declaration:
error: same-type requirement makes generic parameter 'Element' non-generic
What should I do to fix this error?
Is it right to iterate Array
with for value in self
?
Thanks
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"]
or shorter version:
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")
and without reduce functionality:
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")