2016-07-11 4 views
0

У меня есть исходный массив значений фильтра, например:Swift метода фильтра с словарями

let filterValues : [String] = ["1", "4"] 

попытка фильтровать массив словарей, где каждый словарь содержит массив 1 словаря или более.

Форма массива состоит в следующем:

let test : [[String : AnyObject]] = [ 
     ["Objects": 
      [ 
       [ 
        "value":"1", 
        "test":"test" 
       ], 
       [ 
        "value":"1", 
        "test":"test" 
       ], 
       [ 
        "value":"1", 
        "test":"test" 
       ], 
       [ 
        "value":"4", 
        "test":"test" 
       ], 
       [ 
        "value":"2", 
        "test":"test" 
       ], 
       [ 
        "value":"2", 
        "test":"test" 
       ] 
      ] 
     ], 
     ["Objects": 
      [ 
       [ 
        "value":"4", 
        "test":"test" 
       ], 
       [ 
        "value":"2", 
        "test":"test" 
       ], 
       [ 
        "value":"2", 
        "test":"test" 
       ] 
      ] 
     ] 
    ] 

То, что я хочу после применения метода фильтрации на моем первоначальном тестовом массиве:

[ 
      ["Objects": 
       [ 
        [ 
         "value":"1", 
         "test":"test" 
        ], 
        [ 
         "value":"1", 
         "test":"test" 
        ], 
        [ 
         "value":"1", 
         "test":"test" 
        ], 
        [ 
         "value":"4", 
         "test":"test" 
        ] 
       ] 
      ], 
      ["Objects": 
       [ 
        [ 
         "value":"4", 
         "test":"test" 
        ] 
       ] 
      ] 
     ] 

Мой код в детскую площадку:

//Filter objects with matching enabled filters 
let filtered = test.filter({ 
    let currentObjects = $0["Objects"] as! [[String:AnyObject]] 
    let currentsObjectsFiltered = currentObjects.filter({ 
     if let value = $0["value"] as? String { 
      return filterValues.contains(value) 
     } 
     return false 
    }) 
    print(currentsObjectsFiltered) 
    return false 
}) 

Массив «currentsObjectsFiltered» хорошо фильтруется с требуемыми значениями. Но мне нужен исходный массив «filtered» со структурой массива test, а не новый массив, который просто фильтруется с новыми объектами. Я не знаю, что делать с моим фильтрованной массив «currentsObjectsFiltered»

Я думаю, что я должен использовать его теперь, когда я объекты отсортирован, но как ...

EDIT

currentsObjectsFiltered выхода:

[["value": 1, "test": test], ["value": 1, "test": test], ["value": 1, "test": test], ["value": 1, "test": test], ["value": 4, "test": test], ["value": 4, "test": test]] 
[["value": 1, "test": test], ["value": 1, "test": test], ["value": 1, "test": test], ["value": 1, "test": test], ["value": 4, "test": test], ["value": 4, "test": test]] 

не обращайте внимание на количество значений результатов на выходе не имеет один и тот же массив теста, я просто выкладываю выход, чтобы показать вам структуру currentsObjectsFiltered, который хорошо фильтруется.

Я думаю, что не могу сделать это на одном шаге фильтра, потому что метод фильтра применяется только к дочерним элементам фильтрованного массива, а не к дочерним элементам дочерних элементов. Поэтому я могу просто фильтровать «Objects» в соответствии с заявлением, я не могу отфильтровать дочерние слова «Objects» словарей, кто-нибудь может это подтвердить?

Любая помощь? Благодарю.

ответ

2

Это возможно, но типы очень раздражают работу. Если вы обнаруживаете, что создаете новые типы AnyObject, вы почти наверняка приближаетесь к проблеме неправильно. AnyObject в основном существует, поэтому вы можете иметь дело с id типами, которые возвращаются из Какао. Для Swift это не универсальный тип.

Если вы сначала конвертируете их в безопасную по типу структуру, то все это намного проще, и вам не придется постоянно поднимать и опускать все в AnyObject.

Вот простая структура, которая может быть построена из одного из ваших словарей:

struct Object { 
    let value: Int 
    let test: String 

    init?(jsonDictionary: [String: String]) { 
     guard let 
      value = jsonDictionary["value"].flatMap({Int($0)}), 
      test = jsonDictionary["test"] 
      else { return nil } 

     self.value = value 
     self.test = test 
    } 
} 

Преобразования всей структуры данных, в это просто:

let testArray = test.flatMap { 
    ($0["Objects"] as? [[String: String]])? 
     .flatMap(Object.init) 
} 

Затем ее фильтрации, как вы хотите много проще:

let filterValues = [1, 4] 

let filtered = testArray.map { objects in 
    return objects.filter { filterValues.contains($0.value) } 
} 

Даже если вам нужен конечный результат для invo lve AnyObject, я все равно сделаю это так, а затем напишу функцию, чтобы сериализовать ее обратно в исходную структуру AnyObject. Работа непосредственно с AnyObject слишком подвержена ошибкам и сложна. В качестве примера преобразования обратно в AnyObject форме, вы могли бы использовать такую ​​функцию:

func jsonArrayFromObjects(objectList: [[Object]]) -> [[String: AnyObject]] { 
    return objectList.map { objects in 
     ["Objects": objects.map { ["value": "\($0.value)", "test": $0.test] }] 
    } 
} 

Но я бы избежать этого, если это не было абсолютно необходимо. Даже если вам нужен словарь, было бы лучше сделать это [[String: [[String: String]]], а не [[String: AnyObject]].

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