NSPredicate to compare identical string arrays? - ios

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

Related

NSString as float in CoreData predicate

I have CoreData Table with NSString field. But in the filter I need to be interpreted as float.
fieldName.floatValue does not give the correct result. If any way to do this without changing the field type in the table ?
Edit:
Data is:
company = "CompanyName";
date = "2016-01-17";
value = "379.76";
My predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value.floatValue > 2000"];
But value 379.76 enters the result. Using value.floatValue all the same values are compared as strings.
TNX
If you know value is not negative, you can use this trick:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"abs:(value) > 2000"];
The abs: forces SQLite to treat the value attribute as a number.
Alternatively, add zero to it (which works for negative numbers):
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"add:to:(value,0) > 2000"];
I think you should change String type to Number, this is the easiest way.
You can use this predicate:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [[evaluatedObject value] floatValue] > 2000; // Change id to your Class
}];
But this predicate can not be used with CoreData. So you should store the fetch result to an array, then use this predicate with it.
//Try with this.
// '>' will apply when 'value' is number. So, I first put your values in an array. Only then, I can apply the predicate.
NSString *company = #"CompanyName";
NSString *date = #"2016-01-17";
NSString *value = #"379.76";
NSArray *dataArray = #[#(value.floatValue),#(379.76),#(379),#(200)];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self > %f",200.0];
NSArray *array = [dataArray filteredArrayUsingPredicate:predicate];
//output:#(379.76),#(379.76),#(379)
Try this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value > 2000"];

NSPredicate on NSArray of NSDictionary

Imagine you have the following structure for an NSArray of NSDictionary objects:
#define kFlameText #"text"
#define kFlameRelation #"relation"
NSArray* data = #[#{kFlameText:#"TextFlame1", kFlameRelation:#"Relation1"}, #{kFlameText:#"TextFlame2", kFlameRelation:#"Relation2"}, #{kFlameText:#"TextFlame3", kFlameRelation:#"Relation3"}}
You want to use a NSPredicate to extract the dictionary located in second position in your NSArray of NSDictionary based on the NSString #"Relation2"
You tried multiple times, with you last attempt being:
NSPredicate* sortFlames = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", #"Relation2"];
But you are still not there, you still get the following error message:
How would you make it work?
This predicate should do the trick:
NSPredicate *sortFlames = [NSPredicate predicateWithFormat:#"SELF.%K CONTAINS[cd] %#", kFlameRelation, #"Relation2"];
The %K is for the dynamic property name, more info here.

How to filter NSArray using two NSPredcates

I would like to filter an NSArray of NSDictionaries, however I would like to filter the result using one, two or even three NSPredicate values?
Currently I am filtering my array by doing this.
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"parts == %#", filterString];//keySelected is NSString itself
NSMutableArray *filteredArray = [NSMutableArray arrayWithArray:[currentParts filteredArrayUsingPredicate:predicateString]];
sortedItemsArray = [filteredArray mutableCopy];
But I am not sure how I would do this using two predicates?
The other two predicates individually look like the one above accept different keys.
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"area == %#", filterString];
and
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"item == %#", filterString];
What I was thinking is that maybe you could have something like
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"stage == %# area == %#", filterString, areaflterstring];
But I don't think that's possible.
It is possible, but you need to tell the predicate how to combine the parts, like:
NSPredicate *predicateString = [NSPredicate predicateWithFormat:#"stage == %# AND area == %#", filterString, areaflterstring];
You can alternatively use NSCompoundPredicate to combine a number of predicates.

NSPredicate with a NSArray of NSNumbers (Core Data)

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.

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

Resources