NSPredicate, search in a NSArray, inside a NSArray of NSDict - objective-c

I have a NSArray of NSDictionary.
One of the keys of the NSDictionary contains a NSArray of strings.
Is there a way that I can use NSPredicate to find a specific strins in that Array of strings?
Thanks :)
Also: This work great, but not for sublevelArray
predicate = [NSPredicate predicateWithFormat:#" %K LIKE[cd] %#", sKey, sLookForString];

Just replace LIKE with CONTAINS in your format string. For example, given this array:
NSArray *dogs = #[#{#"name" : #"Fido",
#"toys" : #[#"Ball", #"Kong"]},
#{#"name" : #"Rover",
#"toys" : #[#"Ball", #"Rope"]},
#{#"name" : #"Spot",
#"toys" : #[#"Rope", #"Kong"]}];
...the following predicate can be used obtain a filtered array containing only the dictionaries where the value for the key toy is an array that contains the string Kong.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K CONTAINS[cd] %#", #"toys", #"Kong"];

On NSArray you can use filteredArrayUsingPredicate:, on NSDictionary use enumerateKeysAndObjectsUsingBlock: and then for each value do either a filteredArrayUsingPredicate: if it is an NSArray or you can use evaluateWithObject: using the predicate itself.

If you want to filter the array of dictionaries based on the array of strings, you can use -predicateWithBlock to filter the array, as shown in the code below:
- (NSArray *)filterArray:(NSArray *)array WithSearchString:(NSString *)searchString {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSDictionary *dictionary = (NSDictionary *)evaluatedObject;
NSArray *strings = [dictionary objectForKey:#"strings"];
return [strings containsObject:searchString];
}];
return [array filteredArrayUsingPredicate:predicate];
}

Related

Use NSPredicate to filter by index

Basically, what I want to do is this:
NSArray *objectsAtIndex1 = #[[#[#"Foo", #"Bar"] objectAtIndex:1]];
but using NSPredicate instead, so it would look something like this (however this is not working):
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF[1] != null"]
NSArray *objectsAtIndex1 = [#[#"Foo", #"Bar"] filteredArrayUsingPredicate:predicate]
And of course, #"Foo" and #"Bar" are in reality unknown values (and could even be dictionaries or numbers). Is it possible to achieve this?
I solved it by using the predicateWithBlock: method on NSPredicate like this:
NSArray *fooBarArray = #[#"Foo", #"Bar"];
NSUInteger index = 1;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [fooBarArray indexOfObject:evaluatedObject] == index;
}];
NSArray *objectsAtIndex1 = [fooBarArray filteredArrayUsingPredicate:predicate];
One caveat is however that the objects in fooBar-array needs to be unique for this to work, which is not perfect.

Removing elements with same value from NSMutableArray

My NSMutableArray contains some strings as elements. One of the element is repeated many times at different indexes in the array. For example [#"", #"1,2,3",#"",#"5,3,2,1",#""].
I want to remove all the elements with value #"" from the mutable array. I tried following ways but couldn't get the solution.
Using For loop:
for(id obj in myMutableArray)
{
if([obj isEqualToString:#""])
{
[myMytableArray removeObject:obj];
}
}
Using dummy mutable array called nextMutableArray
for(id obj in myMutableArray)
{
if([obj isEqualToString:#""])
{
continue;
}
else [nextMutableArray addObject:obj];
}
In both the ways, elements (#"") at other indexes are removed but not at the index 0 (first object). What could be the possible reason? Is there any way to remove all the elements that contain string #"" from the mutable array?
one option is to filter your array using predicates:
NSArray *someArray = #[#"", #"1,2,3", #"", #"5,3,2,1", #""];
NSLog(#"%#", someArray);
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF != ''"];
NSArray *filteredArray = [someArray filteredArrayUsingPredicate:predicate];
NSLog(#"%#", filteredArray);
No Need of For loop. Simply use this.
[mutableArray removeObjectIdenticalTo:#""];
If you want to remove duplicate entries from an array, You can use NSSet Class.
NSSet did not accept duplicate/s value.
NSMutableArray *arrTest=[[NSMutableArray alloc]initWithObjects:#"", #"1,2,3",#"",#"5,3,2,1",#"", nil];
NSSet *set = [NSSet setWithArray:arrTest];
arrTest = [[set allObjects] mutableCopy];
or
You can do like this:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id str, NSDictionary *unused) { return ![str isEqualToString:#""]; }];
arrTest = [[arrTest filteredArrayUsingPredicate:predicate]mutableCopy];
This is fast and simple way.

Using NSPredicate to filter an NSMutableArray of NSDictionaries to find if a "key" exists

I have an NSMutableArray of dictionaries. I am using NSPredicate to filter through the array to find if a dictionary with a particular key exists or not.
I have referred to various examples, one of the closest is here: Using NSPredicate to filter an NSArray based on NSDictionary keys. However, I don't wish to have a value to the key. My problem is that I want to find the key first. I tried different syntaxes, but it did not help.
What I have done so far:
NSString *key = #"open_house_updated_endhour";
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"%K", key];
//NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"%K contains [cd]", key]; Doesn't work.
//NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"%K == %#", key]; Won't work because it expects a value here.
NSLog(#"predicate %#",predicateString);
NSArray *filtered = [updatedDateAndTime filteredArrayUsingPredicate:predicate]; // updatedDateAndTime is the NSMutableArray
A dictionary delivers nil as value for absent key. So simply compare the key against nil.
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"%K==NULL", key]; // Dictionaries not having the key
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"%K!=NULL", key]; // Dictionaries having the key
Try it:
NSArray *Myarray = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:#"my hello string" forKey:#"name"]];
NSArray *filteredarray = [Myarray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(name == %#)", #"my hello string"]];
NSLog("%#",filteredarray);
Another example :
NSString *mycategory = #"iamsomeone";
NSArray *myitems = #[#{ #"types" : #[#"novel", #"iamsomeone", #"dog"] },
#{ #"types" : #[#"cow", #"iamsomeone-iam", #"dog"] },
#{ #"types" : #[#"cow", #"bow", #"cat"] }];
NSPredicate *mypredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSArray *categories = [evaluatedObject objectForKey:#"types"];
return [categories containsObject:mycategory];
}];
NSArray *outpuArray = [myitems filteredArrayUsingPredicate:mypredicate];
NSLog(#"hello output:%#",outpuArray);

filtering JSON stings array with NSPredicate and regular expression

I have an NSArray containing JSON string like below.
[
{
"title":"find good book",
"isCompleted":true
},
{
"title":"complete work",
"isCompleted":false
},
{
"title":"check schedule",
"isCompleted":false
}
]
I want to find indexes of objects having "plet" value under "title" key. When I just simply used below NSPredicate, it returned every objects, because every JSON objects having "isCompleted" stings as a key.
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", #"plet"];
I don't want to convert JSON to NSDictionary object. And I don't use [NSPredicate predicateWithBlock:], because I am going to apply this predicate to NSFetchedResultsController. According to document, NSPredicate which is created by [NSPredicate predicateWithBlock:] can't be used to NSFetchedResultsController.
So my question is, can I use Regular expression to solve this problem? I don't know much about regular expression. Could anyone give example for this?
You can use predicateWithBlock method for creating your predicate. Inside the block, check whether the dynamicVale contains the value to be searched.
Code:
NSArray *yourArray = ....;
NSString *searchText = ...;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary * _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
NSArray *dynamicVales = [evaluatedObject valueForKeyPath: #"dynamicVales.value"];
return [dynamicVales containsObject:searchText];
}];
NSArray *filteredArray = [yourArray filteredArrayUsingPredicate:predicate];
Copied from JhonyKutties answer. Enjoy coding :)

How to get strings with specific length from NSArray?

I want to get strings that have specific length in NSArray.
The array has many elements and I don't want to use fast enumeration.
Is there a possible way?
This works like a charm:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.length == %d", lenght];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
No matter what you do you will be using fast enumeration whether you realize it or not. However, have you considered using an NSPredicate object and the filteredArrayWithPredicate method?
NSArray *yourArray = [[NSArray alloc] initWithObjects:#"Apple, Orange, Grapes, Cherry, nil"];
for(NSString *element in yourArray){
if(element.length==yourLength){
[filteredArray addObject:element];
}
}
NSLog(#"Filtered array now contains the elements with length %d", yourLength);
NSLog(#"Filtered array--%#", filteredArray);