我正在努力过滤具有不同对象的嵌套数组的对象数组。
EG。我有一系列对象:
class Form {
let name: String
let lasname: String
let roles: [Rule]
// ... init etc.
}
class Rule {
let rule: String
// ... init etc.
}
初始化的数组看起来像:
var forms = [Form]()
let firstRoles: [Rule] = [Rule(rule: "First"), Rule(rule: "Second")]
let secondRoles: [Rule] = [Rule(rule: "Third"), Rule(rule: "Second")]
forms.append(Form(name: "Test1", lastname: "Test2", roles: firstRoles))
forms.append(Form(name: "Test3", lastname: "Test4", roles: secondRoles))
现在我需要通过键过滤forms
。
Keys
:
let keyRoles: [Rule] = [Rule(rule: "First"), Rule(rule: "Second")]
过滤2个元素数组forms
之后,我应该首先获得,因为这两个规则都符合模式。
过滤代码:
forms.filter { (form) in Bool in
return form.roles.contains(where: { (rule) -> Bool in
keyRoles.contains(rule)
})
}
什么都不会返回,一个空数组。 任何想法我做错了什么?
提前致谢!
答案 0 :(得分:1)
您的代码有问题,您正在检查rule
数组中是否存在keyRoles
(这是一个引用)并且始终返回false,因为keyRoles
数组的引用不同于在表格中。因为你已经创建了对象而不是重用它们,虽然内容是相同的但它们位于不同的内存空间。
您在表单中插入了与keyRoles
数组
如果您使用keyRoles
如下
let keyRoles: [firstRoles, secondRoles]
或者在检查
时keyRoles.contains(rule)
您需要添加谓词,以便规则内容与其他规则的内容匹配。即比较内部数据结构而不是比较参考。像下面的东西
let arr = forms.filter { (form) -> Bool in
return form.roles.contains(where: { (rule1) -> Bool in
keyRoles.contains(where: { (rule2) -> Bool in
rule1.rule == rule2.rule
})
})
}
答案 1 :(得分:1)
问题是你正在使用包含,如果任何一个keyRole匹配形式角色,它将返回。但是您的预期结果是keyRoles
必须匹配。
let filtered = forms.filter { (form) -> Bool in
for kr in keyRoles {
if !form.roles.contains(where: { (r) -> Bool in
return r.rule == kr.rule
}) {
return false
}
}
return true
}
注意:如果keyRoles
为空,则不会过滤任何内容(表单==已过滤)
答案 2 :(得分:0)
我会为您的案例(使用contains(where:)方法时)建议非常好的做法,这符合Equatable
协议:
可以比较值相等的类型。
请注意,在使用contains(where:)
时,数组的元素应该是 equatables ,因此您可以让Rule
类成为等同的:
class Rule: Equatable {
let rule: String
static func ==(lhs: Rule, rhs: Rule) -> Bool {
return lhs.rule == rhs.rule
}
// ... init etc.
}
因此,您可以实施:
let filteredForms = forms.filter { form -> Bool in
for rule in keyRoles {
return (form.roles.contains(rule)) ? true : false
}
return false
}
filteredForms
应该包含所需的结果。
显然,通过遵循这种方法,规则实例将是" equatables":
let rule1 = Rule(rule: "First")
let rule2 = Rule(rule: "First")
rule1 == rule2 // true
rule1 != rule2 // false