过滤嵌套结构数组

时间:2021-06-20 18:39:29

标签: swift algorithm struct filter

我正在为以下问题寻找一个很好的快速解决方案:

假设我们有 2 个像这样的结构:

struct Person {
    let name: String
    let age: Int
    let skills: Skills
    init(name: String, age: Int, skills: Skills) {
        self.name = name
        self.age = age
        self.skills = skills
    }

}

struct Skills {
    let canUseBow: Bool
    let canUseSword: Bool
    let canUseShield: Bool
    init(canUseBow: Bool, canUseSword: Bool, canUseShield: Bool) {
        self.canUseBow = canUseBow
        self.canUseSword = canUseSword
        self.canUseShield = canUseShield
    }
}

现在假设我有一个 Person 数组,其中每个人显然都有自己的技能,其中相应的值可以为真或为假。

假设我想要另一个具有技能 canUseBow 为 true 的人的数组,因此必须将技能设置为 true ,我将如何过滤掉没有 canUseBow 的人设置为真?

我考虑的方向是:

filteredPersons = persons.filter {
  $0.skills
}

但是这样就需要我在技能之后选择一些东西 $0.skills.canUseBow

这似乎不是未来的证明,假设我想要添加更多技能,而不是再次更改过滤器方法。有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:3)

您可以使用 OptionSet 尝试此操作,它可以在一个简单的 Int 存储中为您保存所有这些标志。

import Foundation

struct Person {
    let name: String
    let age: Int
    let skills: Skills
    init(name: String, age: Int, skills: Skills) {
        self.name = name
        self.age = age
        self.skills = skills
    }
}

struct Skills: OptionSet {
    let rawValue: Int
    init(rawValue: Int) {
        self.rawValue = rawValue
    }
    
    static let canUseBow = Skills(rawValue: 1 << 0)
    static let canUseSword = Skills(rawValue: 1 << 1)
    static let canUseShield = Skills(rawValue: 1 << 2)
    
    init(json: [String: Bool]) {
        var skills = Skills(rawValue: 0)
        if let canUseBow = json["can_use_bow"], canUseBow {
            skills.insert(.canUseBow)
        }
        if let canUseSword = json["can_use_sword"], canUseSword {
            skills.insert(.canUseSword)
        }
        if let canUseShield = json["can_use_shield"], canUseShield {
            skills.insert(.canUseShield)
        }
        self = skills
    }
}

如何实例化 Skills

let skills = Skills(json: [
    "can_use_bow" : true,
    "can_use_sword" : true,
    "can_use_shield" : false,
])

如何根据多种技能进行筛选?

let targetSkills: Skills = [.canUseBow, .canUseSword]

let persons: [Person] = []
let filteredPersons = persons.filter { 
    targetSkills.isSubset(of: $0.skills)
}