NSPredicate with a NSArray of NSNumbers (Core Data) - ios

I have Core Data entity Field with an attribute of ID. I want to search all Field entities for ID == 1, 2, or 3.
How can I add an array to a NSPredicate w/out creating a long appended string something like:
NSArray *IDArray = #[#1, #2, #3];
NSMutableString *predicateString = [NSMutableString string];
for (NSNumber *ID in IDArray) {
[predicateString appendString:[NSString stringWithFormat:#"ID == %#, ID]];
}

This should work:
NSArray *IDArray = #[#1, #2, #3];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ID IN %#", IDArray];
Remark: You should never use string formatting functions to combine predicates. Use
[NSCompoundPredicate orPredicateWithSubpredicates:...]
and similar methods. The reason is that strings and predicates have different rules how format specifiers are expanded.

Related

Obj-c - Filter array to return dictionaries in which a key contains values listed in NSMutableArray?

I have an array (allFriends) which returns a number of dictionaries (data for about 50 people). Each dictionary contains the key 'uid'. I want to filter allFriends so that all dictionaries in which uid contains the numbers 1,2,3, or 4 are returned.
How might I accomplish this? The numbers I want to filter with are returned in an array, and are grabbed like so:
NSMutableArray *friendUIDs = [self.friendData valueForKey:#"uid"];
This returns the data as: "1, 2, 3, 4"
No matter what I try however (thought NSPredicate would be the way to go), my code doesn't seem to want to let me filter with multiple values separated by a comma?
NSArray *filteredData = [self.allFriends filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(uid contains[c] %#)", friendUIDs]];
Hope I worded this correctly.
Your final predicate should look something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.uid contains[c] %# OR SELF.uid contains[c] %#", #"1",#"2"];
If I understand the question correctly, this should work:
NSMutableArray *friendUIDs = [self.friendData valueForKey:#"uid"];
NSMutableString *predicateString = [NSMutableString string];
for (NSInteger i = 0; i < [friendUIDs count]; i++) {
if (i != 0) {
[predicateString appendString:#" OR "];
}
[predicateString appendFormat:#"SELF.uid contains[c] '%1$#'", friendUIDs[i]];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
NSArray *filteredData = [allFriends filteredArrayUsingPredicate:predicate];

NSPredicate to compare identical string arrays?

Is it possible to use nspredicate to compare whether one NSArray is exactly equal to another NSArray of strings? I need this dome via predicates because of its possible I will add this predicate to a compound predicate.
The Array I am comparing against is a property of an NSDictionary.
So the answer was a mixture of both, I did use the predicatewithformat but got creative in the string inside, inspired by #akashivskyy and #avi
[predicatesArray addObject:[NSPredicate predicateWithFormat:#"ANY dynamic.values == %#", arr]];
Edit: As (partially) suggested by Avi, you may use the equality predicate:
NSArray *otherArray = #[ #"foo", #"bar" ];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self == %#", otherArray];
[predicate evaluateWithObject:#[ #"foo", #"bar" ]]; // YES
[predicate evaluateWithObject:#[ #"baz", #"qux" ]]; // NO
Alternatively, and if you have any trouble with format string in the future, you may always use a block predicate to perform your own logic:
NSArray *otherArray = #[ #"foo", #"bar" ];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^(NSArray *evaluatedArray, NSDictionary<NSString *, id> *bindings) {
return [evaluatedArray isEqualToArray:otherArray];
}];
// use the predicate

Using predicate to find if string value exists

I have a NSMutableArray of objects with tag attributes assigned to them. I am trying to find if any of these objects have a tag assigned to them of the string value "a".
my code so far:
for (Object *object in self.array)
{
NSDictionary *attrs = [object propertyValue:#"attrs"];
NSString *tag = attrs[#"tag"];
}
Can I do something like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"a"];
NSArray *results = [self.array filteredArrayUsingPredicate:predicate];
not sure how it works?
Try this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"tag == %#", #"a"];
NSArray *result = [NSMutableArray arrayWithArray:[self.array filteredArrayUsingPredicate:predicate]];
Use 'contains[c]' instead of '==' if you want to perform case-insensitive search.
If you want to filter for any other property, replace 'tag' with that property name.
You will need to do something more like :
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.property_name contains[c] '%#'", #"a"];
NSArray *result = [NSMutableArray arrayWithArray:[self.array filteredArrayUsingPredicate:predicate]];

Plist NSPredicate in iOS

I have a plist working with a search display controller which contains an array of dictionaries with some data members like.
<root> (array)
<"Item 0"> (dictionary)
<"Name"></"Name" (String)
<"Work"></"Work"> (String)
<"Age"></"Work"> (Number)
</"Item 0">
<"Item 1">
....
</"Item 1">
</root>
I would like to use an NSPredicate to filter all the names that match with the search criteria. For example searching "an" for all names will yield "Sandy" and "Alexander."
So far I've tried things like:
NSPredicate *p = [NSPredicate predicateWithFormat:#"Name == %#",
filterText];
Results = [data filteredArrayUsingPredicate:p];
Any ideas? Thanks.
Use CONTAINS in NSPredicate
Below code gives case sensitive search
NSPredicate *p = [NSPredicate predicateWithFormat:#"Name CONTAINS %#",
filterText];
Results = [yourPlistDataArray filteredArrayUsingPredicate:p];
Below code gives case insensitive search
NSPredicate *p = [NSPredicate predicateWithFormat:#"ANY Name CONTAINS %#",
filterText];
Results = [yourPlistDataArray filteredArrayUsingPredicate:p];
EDIT : Refer more here
this can show you the very generic type of the searching in any NSArray. it is adjusted to your NSDictionary items currently, but you can create even more complex conditions here to filter it.
NSArray *originalArray = ...;
NSString *searchText = ...; // this is a parameter only, it can be set freely
NSArray *_filteredArray = [originalArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSDictionary *_dataRow = (NSDictionary *)evaluatedObject;
return ([[[_dataRow valueForKey:#"Name"] lowercaseString] rangeOfString:[searchText lowercaseString]].location != NSNotFound);
}]];
NSLog (#"%#", _filteredArray);

dynamically generate NSPredicate from an NSArray

I have a large number of different NSObject types that all have different properties and I am trying to abstract out a single method that will allow me to filter the NSArrays of the objects by simply passing in an NSArray of properties I wish to filter on. The number keys I filter on vary from possibly 1 to whatever.
Here is an example of the filtering NSArray
NSArray *filterBy = [NSArray arrayWithObjects:
#"ManufacturerID",
#"CustomerNumber",nil];
These keys also exist in the objects of my NSArray I am filtering, so basically this would need to generate something like this:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K == %# AND %K == %#",
[filterBy objectAtIndex:0],
[items valueForKey: [filterBy objectAtindex:0],
[filterBy objectAtIndex:1],
[items valueForKey: [filterBy objectAtIndex:1]];
Which would generate something like: ManufacturerID==18 AND CustomerNumber=='WE543'
Is it possible to do this?
This is easy. Check it out:
NSMutableArray *subpredicates = [NSMutableArray array];
for (NSString *filterKey in filterBy) {
NSString *filterValue = [items valueForKey:filterKey];
NSPredicate *p = [NSPredicate predicateWithFormat:#"%K = %#", filterKey, filterValue];
[subpredicates addObject:p];
}
NSPredicate *final = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];

Resources