2016-10-18 5 views
1

У меня есть этот массив словарей:Swift 3 - расширить массив словаря <String, Any>

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 ation: error: same-type requirement makes generic parameter 'Element' non-generic

Что мне делать, чтобы исправить это?

Правильно ли итератировать Array с for value in self?

Благодаря

ответ

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

Объединенного раствора с 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.flatMap {$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") 
} 

Best,

 Смежные вопросы

  • Нет связанных вопросов^_^