Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Predicate to filter an array by a property of member array

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

like image 499
jincy abraham Avatar asked Oct 17 '16 08:10

jincy abraham


People also ask

What is Nspredicate in Swift?

A definition of logical conditions for constraining a search for a fetch or for in-memory filtering.

How do I filter a string array in Swift?

To filter strings in a Swift String Array based on length, call filter() method on this String Array, and pass the condition prepared with the string length as argument to the filter() method. filter() method returns an array with only those elements that satisfy the given predicate/condition.

What is mutable array in Swift?

If you create an array, a set, or a dictionary, and assign it to a variable, the collection that's created will be mutable. This means that you can change (or mutate) the collection after it's created by adding, removing, or changing items in the collection.


1 Answers

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 }) }
like image 117
Martin R Avatar answered Nov 04 '22 01:11

Martin R