NSPredicate find an array inside db - ios

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];

Related

An array of id to filter an Array via NSPredicate

The following predicate works if I only pass a single itemId but I wonder what if I have multiple itemId s, how could I able to make it work ?
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(%K == %#)", kItemId, itemId];
NSArray *filteredArray = [restaurantData.itemArray filteredArrayUsingPredicate:predicate];
You can do IN query:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(%K IN %#)", kItemId, yourArrayOfItemId];

NSPredicate to handle NIL string as ANY character

I have an NSPredicate looks like that:
NSPredicate *predicateSearch;
if ([category_array count]>0 && [location_array count]>0) {
predicateSearch =[NSPredicate predicateWithFormat:#"category_id IN %# AND location_id IN %# AND company_title CONTAINS %#",category_array,location_array,searchStr];
}
else if ([category_array count]>0){
predicateSearch =[NSPredicate predicateWithFormat:#"category_id IN %# AND company_title CONTAINS %#",category_array,searchStr];
}
else if([location_array count]>0){
predicateSearch = [NSPredicate predicateWithFormat:#"location_id IN %# AND company_title CONTAINS %#",location_array,searchStr];
}
[fetchRequest setPredicate:predicateSearch];
Since NSPredicate is not able to handle Nil values I am using this If-Statement to format the Predicate and handle the Nilvalue as 'ANY'.
The issue here is that I want also the searchStr to be handled as 'ANY' if it's Nil.
I tried to set it as empty string in case of Nil but it won't work.
Is there any way to accomplish that without using any If-statements for each case(9 if-statements it's too much)?
Use compound predicates. Example, based on what you posted:
NSPredicate *categoryPredicate = (category_array.count > 0)
? [NSPredicate predicateWithFormat:#"category_id IN %#", category_array]
: [NSPredicate predicateWithValue:YES];
NSPredicate *locationPredicate = (category_array.count > 0)
? [NSPredicate predicateWithFormat:#"location_id IN %#", location_array]
: [NSPredicate predicateWithValue:YES];
NSPredicate *searchPredicate = (searchStr.length > 0)
? [NSPredicate predicateWithFormat:#"company_title CONTAINS %#", searchStr]
: [NSPredicate predicateWithValue:YES];
NSCompoundPredicate *predicate =
[NSCompoundPredicate
andPredicateWithSubpredicates:#[
categoryPredicate,
locationPredicate,
searchPredicate,
]
];

Coredata predicate IN operator with like or contain

I have two arrays on which I have to do the wildcard search and I am using the IN operator but the IN operator gives me the exact matching but I want to fetch all the results that contains the searchTerm. Is this possible through IN operator or do I have to manually loop through all the records and match pick the record that I want.
Current Code :
NSArray *filteredArray = [brandsFabric filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.color_name IN %# OR self.subcategory_name IN %#",colorNamesArray,patternNamesArray]];
Desired functionality something like this:
NSArray *filteredArray = [brandsFabric filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.color_name IN like/contains %# OR self.subcategory_name IN like/contains %#",colorNamesArray,patternNamesArray]];
This is a very expensive operation, but you can try:
NSMutableArray *predicates = [NSMutableArray array];
for (NSString *name in colorNames) {
[predicates addObject:[NSPredicate predicateWithFormat:
#"color_name CONTAINS[cd] %#", name]];
}
for (NSString *name in subcategoryNames) {
[predicates addObject:[NSPredicate predicateWithFormat:
#"subcategory_name CONTAINS[cd] %#", name]];
}
NSPredicate *final = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
Maybe even a subquery is in order here. (experimental)
[NSPredicate predicateWithFormat:
#"((SUBQUERY(%#, $x, color_name CONTAINS[cd] $x).#count != 0) OR "
#"((SUBQUERY(%#, $x, category_name CONTAINS[cd] $x).#count != 0)",
colorNames, categoryNames];
It goes like this : CONTAINS[cd] %# in place of IN

How to use a compound NSPredicate?

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.

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"]];

Resources