Inverse of values using NSPredicate IOS - ios

NSArray *arrValues = [NSArray arrayWithObjects:#"ABCD",#"ABCE",#"CDE"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS[cd]%#",#"ABC"];
NSArray *arrFiltered = [arrValues filteredArrayUsingPredicate:predicate];
I am aware that arrFiltered will contain the result ABCD and ABCE.
But, I want the result as CDE.
Is there a way to find the inverse of the predicate specified. ie., !(ABC)

Try to use NOT with predicate
NSArray *arrValues = [NSArray arrayWithObjects:#"ABCD",#"ABCE",#"CDE"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (SELF CONTAINS[cd] %#"),#"ABC"];
NSArray *arrFiltered = [arrValues filteredArrayUsingPredicate:predicate];

try
[NSPredicate predicateWithFormat:#"SELF !=[c] %#",#"ABC"];
The [c] makes the equality comparison case-insensitive.
Option-2
NSArray *arrValues = [NSArray arrayWithObjects:#"ABCD",#"ABCE",#"CDE",nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (SELF CONTAINS %#)",#"ABC"];
NSArray *arrFiltered = [arrValues filteredArrayUsingPredicate:predicate];
you get output as

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

NSPredicate for filtering array with ( ' ) character issue

Here is my test for filtering the array by a string. It work well if my string doesn't contain (') character
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b''"]; -> it crash
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
I also try to change my string to 'b\'' or 'b''' but it still crash
Here is the crash log
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "SELF contains[c] 'b'''"'
How to resolve it? Any help would be great appreciated.
Please try to filter result as follows:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSString *strToBeSearched = #"b'";
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",strToBeSearched]; //-> it also work
//OR
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"containB = %#",beginWithB);
try this
NSString *searchword = #"b";
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",searchword];
you get output of
You were pretty close when you tried backslash. This is the character that NSPredicate uses to escape special characters. However, you need two, not one, backslash:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
// ^^
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
The reason you need two is Objective-C compiler. It processes all string literals in your code, and replaces escape sequences it encounters. If you would like NSPredicate to see a single backslash, your string literal needs to have two backslashes, because backslash itself is encoded as \\ in Objective-C string literals.
If your name is b'en then,
NSString *name = #"b'en";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == \"%#\"", name];
Hope this will help :)

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

NSPredicate search LIKE

i'm trying to filter a string array with this predicate:
[NSPredicate predicateWithFormat:#"SELF LIKE[c] '#*!%d'", aNumber]
Every string which is like #WILDCARD!ANY_NUMBER is valid.
But it doesn't work :(
Can you help me?
EDIT:
NSString *pattern = [#"#*!" stringByAppendingFormat:#"%d", numberVariable];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pattern];
NSArray *filteredArray = [anArray filteredArrayUsingPredicate:pred];
The array anArray contains Strings like #0!-1 (numberVariable is -1) but the array filterdArray is empty. So the regex doesn't work.
EDIT:
My Solution:
NSString *pattern = [#"#.*!\\" stringByAppendingFormat:#"%d", numberVariable];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pattern];
NSArray *filteredArray = [anArray filteredArrayUsingPredicate:pred];
To find all strings that look like "#ANY_CHARACTERS!ANY_NUMBER" with an arbitrary number, you need the "MATCHES" operator with a regular expression:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", #"#.*!\\d+"];
NSArray *filtered = [yourArray filteredArrayUsingPredicate:pred];
If you have a specific number aNumber and want to find all strings of the form
"#ANY_CHARACTERS!<aNumber>", then the following should work:
NSString *pattern = [#"#*!" stringByAppendingFormat:#"%d", aNumber];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF LIKE %#", pattern];
NSArray *filtered = [yourArray filteredArrayUsingPredicate:pred];
The problem with your
[NSPredicate predicateWithFormat:#"SELF LIKE[c] '#*!%d'", aNumber]
is that %d inside quotation marks is not replaced by aNumber.

Resources