简体   繁体   中英

Find objects that include an array that contains all elements of a second array

I'm trying to filter a set of objects based on values in one of their elements based on another array. I've got it working with filter just fine if the search is "OR" - it returns give me all objects for which at least one of the strings in the search array is found.

But I can't figure out how to make it work as an AND search - returning only the objects that match ALL of the strings in the search array.

Example:

struct Schedule {
    let title: String
    let classTypes: [String]
}

let schedule1 = Schedule(title: "One", classTypes: ["math","english","chemistry","drama"])
let schedule2 = Schedule(title: "Two", classTypes: ["pe","math","biology"])
let schedule3 = Schedule(title: "Three", classTypes: ["english","history","math","art"])

let schedules = [schedule1, schedule2, schedule3]

let searchArray = ["math", "english"]

//works for OR - "math" or "english"
var filteredSchedules = schedules.filter { $0.classTypes.contains(where: { searchArray.contains($0) }) }

I'd like to find a way for it to use the same search array

let searchArray = ["math", "english"]

But only return items 1 & 3 - as they both have BOTH math and english in the list.

There are good examples of AND conditions when the AND is across different search criteria: car type and colour - but I've been unable to find an example where the criteria are dynamically based on items in an array. For context, I could have dozens of schedules with 20+ class types.

You can work with a Set, isSubset will return true if the schedules element contains all elements of the searchSet

let searchSet = Set(searchArray)
var filteredSchedules = schedules.filter { searchSet.isSubset(of: $0.classTypes) }

As suggested by @LeoDabus it might be worth changing the type of classTypes to Set instead of arrays (if order doesn't matter) since they seems to be unique and then the filtering can be done in the opposite way without the need to convert searchArray each time

var filteredSchedules = schedules.filter { $0.classTypes.isSuperset(of: searchArray) }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM