通过其他数组元素过滤嵌套数组

时间:2017-10-25 07:31:48

标签: swift

我正在努力过滤具有不同对象的嵌套数组的对象数组。

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)
   })
}

什么都不会返回,一个空数组。 任何想法我做错了什么?

提前致谢!

3 个答案:

答案 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