How to use a compound NSPredicate? - ios

I would like to know how if at all to use a compound NSPredicate?
I have made an attempt as follows however the currentInstall array is exactly the same at the start as it is after the predicate has been applied.
NSArray *currentInstall = [coreDataController filterReadInstalls:selectedInstallID];
NSArray *tempArray = [currentInstalls filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"cHR == 0"]];
currentInstalls = [tempArray copy];
NSPredicate *predicateAreaString = [NSPredicate predicateWithFormat:#"area == %#", [myFilter objectForKey:#"area"]];
NSPredicate *predicateBString = [NSPredicate predicateWithFormat:#"stage == %#", [myFilter objectForKey:#"area2"]];
NSPredicate *predicateCString = [NSPredicate predicateWithFormat:#"partCode == %#", [myFilter objectForKey:#"area3"]];
NSPredicate *predicateDString = [NSPredicate predicateWithFormat:#"doorNo CONTAINS[cd] %#", [myFilter objectForKey:#"door"]];
NSPredicate *predicateEString = [NSPredicate predicateWithFormat:#"doorDesc CONTAINS[cd] %#", [myFilter objectForKey:#"doorDesc"]];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[predicateAreaString, predicateBString, predicateCString, predicateDString, predicateEString]];
NSMutableArray *filteredArray = [NSMutableArray arrayWithArray:[currentInstalls filteredArrayUsingPredicate:compoundPredicate]];
currentInstalls = [filteredArray mutableCopy];

There doesn't seem to be anything obviously wrong with the way you have implemented NSCompundPredicate. If you are not trying to And or Not predicates then I would say it is something wrong with your predicate formats and how they match the array you are filtering.
I would try to use just 2 of the predicates to create an NSCompundPredicate then get that working or see what is causing your issue. NSHipster also has some good info about NSPredicates.

Related

How to filter model by its property?

I have a modelArr:
NSArray<MyModel *> *modelArr = xxx;
And in the MyModel, has property, such as type.
How can I filter the modelArr to get a new Array only have the same type?
You can use NSPredicate for that.
Compare type property with specific value.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"type = %#", searchType];
NSArray *filterArray = [modelArr filteredArrayUsingPredicate:predicate];
If you want to check type property contains specific value than
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"type contains[cd] %#", searchType];
NSArray *filterArray = [modelArr filteredArrayUsingPredicate:predicate];
You can use NSPredicate, Please use this code
NSPredicate *bPredicate = [NSPredicate predicateWithFormat:#"SELF.name contains[cd] %#",self.searchText.text];
self.filteredArray = [self.hotelArray filteredArrayUsingPredicate:bPredicate];
NSLog(#"HERE %#",self.filteredArray);`
Try this
NSArray *uniqueNames = [modelArr valueForKeyPath:#"#distinctUnionOfObjects.type"];

Searching dictionary in array using predicate

I have an array of dictionaries and I want to find the dictionary with desired value for key "guid".
Can not get it with this code:
NSPredicate *filter = [NSPredicate predicateWithFormat:#"guid = %#", key];
NSArray *filteredContacts = [selectedValue filteredArrayUsingPredicate:filter];
Try this.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Name CONTAINS[cd] %#",searchBar.text];
filterdArray = [[hospitalArray filteredArrayUsingPredicate:predicate] mutableCopy];
Where Name is the key contained in the dictionary under the array.
I think you forgot "=" sign.
NSPredicate *filter = [NSPredicate predicateWithFormat:#"guid == %#", key];
NSArray *filteredContacts = [selectedValue filteredArrayUsingPredicate:filter];
The operator condition has been forgotten ;)
You need to add a double "=" like this :
NSPredicate *filter = [NSPredicate predicateWithFormat:#"guid == %#", key];
NSArray *filteredContacts = [selectedValue filteredArrayUsingPredicate:filter];
I hope this can help you !
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(guid CONTAINS[c] %#)",key];
NSArray *array = [[NSArray arrayWithArray:sampleArray] filteredArrayUsingPredicate: predicate];
in above code "fromDate" is key of dictionary.
i hope this works for you.
Try this,
NSArray *filtered = [array_with_dict filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(guid == %#)", #"desired value"]];
You could try to initiate the NSPredicate as:
NSPredicate *filter = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"guid = '%#'", key]];
Hope it helps.

NSPredicate find an array inside db

I have the DB that contains an
NSString *Number
NSSet *Values
I can easily get all the results based on the string Number with the following:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Number LIKE[c] %#", numberValue];
NSArray *result = [DB MR_findAllWithPredicate:predicate inContext:_context];
If instead of Number I want to pass an Array of values, how can I find in db all the results that contain the given array (NSSet)?
NSPredicate *predicate = [NSPredicate predicateWithFormat: ????
NSArray *result = [DB MR_findAllWithPredicate:predicate inContext:_context];
UPDATE
Based on Igoris answer :
[NSPredicate predicateWithFormat:#“(Values.#count == %d) AND (SUBQUERY(Values, $x, $x IN %#).#count == %d)", allValues.count, allValues, allValues.count];
This seem to work but it doesn t return all the values in result.
Just use IN:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Number IN[c] %#", numberValues];
Where numberValues is NSArray containing numbers you are looking for
UPDATE:
After data structure clarifications I came up with the following predicate to get objects:
[NSPredicate predicateWithFormat:#“(Values.#count == %d) AND (SUBQUERY(Values, $x, $x IN %#).#count == %d)", allValues.count, allValues, allValues.count];
How about ANY and NONE?
[NSPredicate predicateWithFormat:#"ANY number == %#", numberValues];

NSPredicate and NSArray

Is there a way to setup a NSPredicate that will search for all items in an NSArray?
something like:
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"group.name == %#", arrayOfNames];
Use "IN" instead of "==" if the right-hand side is an array or set:
[NSPredicate predicateWithFormat: #"group.name IN %#", arrayOfNames]
Yes you can use NSPredicate with NSArray like this
NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:#"foo" forKey:#"BAR"]];
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(BAR == %#)", #"foo"]];

NSPredicate to arrange NSMutableArray Objects?

I have multiple category list(around 45). i want to show some of the category to first like (Helicopter,Lake Monster,Dinosaur Attack) that will come at the starting after this remaning other will come. i have used the following code.
That works fine. But its to lengthy. so i want to filter this code.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF IN %#", #[#"Helicopter", #"Lake Monster",#"Dinosaur Attack"]];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Helicopter"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Lake Monster"];
NSPredicate *predicate3 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Dinosaur Attack"];
NSMutableArray *filteredArray = [[NSMutableArray alloc]init];
NSArray *arr1=[packages filteredArrayUsingPredicate:predicate1];
NSArray *arr2=[packages filteredArrayUsingPredicate:predicate2];
NSArray *arr3=[packages filteredArrayUsingPredicate:predicate3];
[filteredArray insertObject:[arr1 objectAtIndex:0] atIndex:0];
[filteredArray insertObject:[arr2 objectAtIndex:0] atIndex:1];
[filteredArray insertObject:[arr3 objectAtIndex:0] atIndex:2];
[packages removeObject:[arr1 objectAtIndex:0]];
[packages removeObject:[arr2 objectAtIndex:0]];
[packages removeObject:[arr3 objectAtIndex:0]];
So is there any way to achieve this result with shortest method?
Just cleaning up your own code, you could do the following:
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Helicopter"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Lake Monster"];
NSPredicate *predicate3 = [NSPredicate predicateWithFormat:#"packageName CONTAINS[cd] %#", #"Dinosaur Attack"];
NSMutableArray *filteredArray = [[NSMutableArray alloc]init];
for (NSPredicate *predicate in #[predicate1, predicate2, predicate3]) {
NSArray *arr=[packages filteredArrayUsingPredicate:predicate];
[filteredArray addObject:arr[0]];
[packages removeObject:arr[0]];
}
You should probably create a class (lets call it STOElement) that has two properties, (NSString*)text, and (NSNumber*)order. Create an instance of that class for each element 'Helicopter' etc, set that as the text, and then set the order you would like that element to appear in as the order (1,2,3 etc).
Then use the sortedArrayUsingComparator: to get an array with the order you want
NSArray* sortedArray = [arrayOfElements sortedArrayUsingComparator:^NSComparisonResult(STOElement* element1, STOElement* element2) {
return [element1.order compare:element2.order];
}];

Resources