Home > Blockchain >  Checking if any element in one array exists in another
Checking if any element in one array exists in another

Time:06-10

I am trying to create a filtering system for some items by checking if the selected items exist in the presented values.

So my selectable array can range from 0 to 6, and each item contains an array of Ints that it is associated with:

let items = [
 Item(cat: [1, 2, 3]),
 Item(cat: [0, 6]),
 Item(cat: []),
 Item(cat: [0, 1])
]

I wanted to create a function that would check if any of the cat values were in the selected Ints:

@Published var filteredCats: [Int] = []

func filterByInt(array: [Item]) -> [Item] {
 let output = array.filter({
  guard let cats = $0.cats else { return true }

  for cat in cats {
   return filteredCats.contains(cat)
  }
 })
 return output
}

But I'm having issue with the above since it returns in the loop on the first iteration, so if I was searching for 1 in the above items then Item(cat: [0, 1]) exits at false as the first looped check is 0==1.

Essentially I want to be able to do the following (in expanded terms):

let filter = [0, 3, 4]
let items = [
 [1, 2, 3],
 [2, 3],
 [],
 [5, 6, 7]
]

items.contains(filter) // --> return the arrays

Sorry if this is basic but I've been trying to find a good solution.

CodePudding user response:

Checking uniqueness is where a Set can help

struct Item {
    var cat: Set<Int>
}

let items = [
 Item(cat: [1, 2, 3]),
 Item(cat: [0, 6]),
 Item(cat: []),
 Item(cat: [0, 1])
]

let wanted: Set<Int> = [0, 3, 4]

let filtered = items.filter { !$0.cat.isDisjoint(with: wanted) }

CodePudding user response:

I'd suggest someSatisfy (or any in Kotlin):

We can utilize allSatisfy with double negations (one for allSatisfy, the other for contains) for that:

struct Item: CustomDebugStringConvertible {
    let cat: [Int]
    
    var debugDescription: String {
        "["   cat.map { String($0) }.joined(separator: ", ")   "]"
    }
}

func filterByInt(items: [Item], filter: [Int]) -> [Item] {
    // Early return might make sense if the filter is empty.
    // guard !filter.isEmpty else { return items }
    
    items.filter { item in
        !filter.allSatisfy {
            filterItem in !item.cat.contains(filterItem)
        }
    }
}

let filter = [0, 3, 4]
let items: [Item] = [
    .init(cat: [1, 2, 3]),
    .init(cat: [2, 3]),
    .init(cat: []),
    .init(cat: [5, 6, 7])
]

print(filterByInt(items: items, filter: filter))
// [[1, 2, 3], [2, 3]]

print(filterByInt(items: items, filter: [5]))
// [[5, 6, 7]]

print(filterByInt(items: items, filter: []))
// []
  • Related