Reputation: 1451
Let say I have two different struct
struct ItemA:Hashable, Codable, Identifiable {
var id: Int
var itemBId: [Int]
}
struct ItemB:Hashable, Codable, Identifiable {
var id: Int
var isSelected: Bool
}
Assume that I have a list of ItemA and ItemB objects called "itemAs" and "itemBs" respectively.
Some of the itemBs object may have isSelected = true.
I therefore want to filter and show only the ItemA object, with a itemB index, which is in the list of itemBs's true case.
var filteredItemAbyItemB: [Bird] {
let itemBFilter = modelData.itemBs.filter {$0.isSelected})
modelData.itemAs.filter {
itemA -> Bool in
itemBFilter.contains(itemA.itemBId) // fail here
}
}
May I know how to do that?
Example ItemB objects:
ib1 = {1, true}
ib2 = {2, false}
ib3 = {3, true}
itemBFilter should contain objects ib1 and ib3
ItemA objects:
ia1 = {1, [1,2]} // should appear in the final list, cause has itemBid = 1
ia2 = {2, [1]} // should appear in the final list, cause has itemBid = 1
ia3 = {3, [2]}
ia4 = {4, [2,3]} // should appear in the final list, cause has itemBid = 3
The final filtered result should contains objects ia1, ia3, and ia4
Upvotes: 0
Views: 192
Reputation: 1228
It's best to use Sets for this to avoid multiple contains:
let selectedBIds = modelData.itemBs
.filter { $0.isSelected }
.map(\.id)
let filteredAWithAllBsSelected = modelData.itemAs.filter { Set($0.itemBId).isSubset(of: selectedBIds) }
let filteredAWithAtLeastOneBSelected = modelData.itemAs.filter { !Set($0.itemBId).intersection(selectedBIds).isEmpty }
Note that you didn't specify in your question whether you wanted all b's to be selected, but your expected outcome made that clear. Maybe you also have to think about empty b's so do you want a's without any b's to also be in your result? It comes down to whether you expect at least one b to be selected or not all of the b's to not be selected
Upvotes: 0
Reputation: 619
I think you can try this
// Your items
let itemsB = [ItemB(id: 1, isSelected: true),
ItemB(id: 2, isSelected: false),
ItemB(id: 3, isSelected: true)]
let itemsA = [ItemA(id: 1, itemBId: [1, 2]),
ItemA(id: 2, itemBId: [1]),
ItemA(id: 3, itemBId: [2]),
ItemA(id: 4, itemBId: [2, 3])]
// I filter and map itemsB to get selected Ids
let itemsBselectedIds = itemsB.filter { $0.isSelected }.map { $0.id }
// Then I filter itemsA to verify if the itemA has a selected Id from itemsB
let filter = itemsA.filter { itemA in
itemsBselectedIds.contains(where: { itemA.itemBId.contains($0) })
}
In your code you try to verify if itemsB contains itemA.id
, but itemsB is an array of ItemB
not an array of id [Int]
Upvotes: 1