带字典的Swift过滤方法

时间:2016-07-11 13:39:47

标签: swift

我有一个初始的过滤器值数组,例如:

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

我尝试过滤一个字典数组,其中每个字典包含一个或多个字典的数组。

数组的形式如下:

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

在我的初始测试数组上应用filter方法后我想要的是什么:

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

我认为我必须使用它,因为我已经对对象进行了排序,但是如何......

修改

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"字典,任何人都可以确认吗?

有任何帮助吗?感谢。

1 个答案:

答案 0 :(得分:2)

这是可能的,但这些类型非常烦人。如果您发现自己正在创建新的AnyObject类型,那么您几乎肯定会错误地解决问题。 AnyObject主要存在,因此您可以处理从Cocoa返回的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) }
}

即使您需要最终结果涉及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]]