5

I need to filter out an array of MyClass3 Objects. An array of MyClass2 Objects is a member of MyClass3 object(Please refer to code below). MyClass2 object has an id. I have an idArray at hand. I need to filter out those MyClass3 objects in which all ids in idArray are present in its [MyClass2] member.

class MyClass2 : NSObject {
    var uid: Int = 0

    init(uid : Int) {
        self.uid = uid
    }
}

class MyClass3 : NSObject {
    var arr: [MyClass2]

    init(units: [MyClass2]) {
        arr = units
    }
}

var units1 = [MyClass2(uid: 1),MyClass2(uid: 2), MyClass2(uid: 3), MyClass2(uid: 4), MyClass2(uid: 5)]
var units2 = [MyClass2(uid: 4),MyClass2(uid: 5), MyClass2(uid: 6)]
var units3 = [MyClass2(uid: 3),MyClass2(uid: 5), MyClass2(uid: 7), MyClass2(uid: 1)]

var ids = [1,5]

var available3: [MyClass3] = [MyClass3(units: units1), MyClass3(units: units2), MyClass3(units: units3)]
var filtered3: [MyClass3] = []

let searchPredicate: NSPredicate = NSPredicate(format: " ANY arr.uid IN \(ids)") // needed predicate
print(searchPredicate.predicateFormat)
filtered3 = (available3 as NSArray).filteredArrayUsingPredicate(searchPredicate) as! [MyClass3]

The required answer is that we need MyClass3(units: units1) and MyClass3(units: units3) in the filtered Array.

This is not working out. Can someone suggest a predicate format for this purpose

jincy abraham
  • 579
  • 2
  • 9
  • 21

3 Answers3

10

Using string interpolation in predicate format strings is never a good idea. The correct form of your predicate would be

let searchPredicate = NSPredicate(format: "ANY arr.uid IN %@", ids)

However that checks if any of the uids is in the given list. To check if all uids are in the given list, the following predicate should work:

let searchPredicate = NSPredicate(format: "SUBQUERY(arr.uid, $x, $x IN %@).@count = %d", ids, ids.count)

The same can be achieved without predicates in "pure" Swift 3 as

filtered3 = available3.filter { $0.arr.filter { ids.contains($0.uid) }.count == ids.count }

or

filtered3 = available3.filter { Set(ids).isSubset(of: $0.arr.map { $0.uid }) }
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
1

You can do using perform intersection operation instead of NSPredicate:

Refer below link for this

Set operations (union, intersection) on Swift array?

Community
  • 1
  • 1
KKRocks
  • 8,222
  • 1
  • 18
  • 84
  • Am not able to do this directly as I have a custom array which contains another custom array which is to be filtered out using an idArray. – jincy abraham Oct 17 '16 at 08:43
  • you can do using this operation but you need to do some logic for what you want in result . – KKRocks Oct 17 '16 at 08:48
0

You can check out this link for good examples but for filtering of arrays you can use something like :

filteredArray = wholeArray.filter{ !unwantedArray.contains($0)}
AMAN77
  • 6,218
  • 9
  • 45
  • 60