dynamically generate NSPredicate from an NSArray - ios

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

Related

Obj-C - Filter multiple keys by text in searchbar?

I'm trying to filter two keys with the text in my search bar. See my code below so far, but it crashes my app.
NSSet *keys = [NSSet setWithObjects:#"node_title", #"address", nil];
self.filteredStores = [self.storesData filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"%K contains[c] %#", keys, self.searchBar.text]];
I feel like I'm on the right track, but I'm unable to do this successfully. Help is appreciated!
One option...
NSSet *keys = [NSSet setWithObjects:#"node_title", #"address", nil];
NSMutableArray *subpredicates = [NSMutableArray array];
for (NSString *k in keys) {
NSPredicate *p = [NSPredicate predicateWithFormat:#"%K contains[c] %#", k, self.searchBar.text];
[subpredicates addObject:p];
}
NSPredicate *final = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];
self.filteredStores = [self.storesData filteredArrayUsingPredicate:final];

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

How to write predicate to filter array of dictionaries?

I have array of dictionaries, dictionary contains key as NSString and value as integer. I have tried the following code but not getting result.
NSPredicate *objPredicate = [NSPredicate predicateWithFormat:#"%# = %#", key, [NSNumber numberWithInt:value]];
NSArray *filteredArray = [array filteredArrayUsingPredicate:objPredicate];
Use this:
NSPredicate *objPredicate = [NSPredicate predicateWithFormat:#"self[%#] = %#", key, #(value)];
NSArray *filteredArray = [array filteredArrayUsingPredicate:objPredicate];

Filter array by first letter of string property

I have an NSArray with objects that have a name property.
I would like filter the array by name
NSString *alphabet = [agencyIndex objectAtIndex:indexPath.section];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSMutableArray *listSimpl = [[NSMutableArray alloc] init];
for (int i=0; i<[[Database sharedDatabase].agents count]; i++) {
Town *_town = [[Database sharedDatabase].agents objectAtIndex:i];
[listSimpl addObject:_town];
}
NSArray *states = [listSimpl filteredArrayUsingPredicate:predicate];
But I get an error - "Can't do a substring operation with something that isn't a string (lhs = <1, Arrow> rhs = A)"
How can I do this? I would like to filter the array for the first letter in name being 'A'.
Try with following code
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF like %#", yourName];
NSArray *filteredArr = [yourArray filteredArrayUsingPredicate:pred];
EDITED :
NSPredicate pattern should be:
NSPredicate *pred =[NSPredicate predicateWithFormat:#"name beginswith[c] %#", alphabet];
Here is one of the basic use of NSPredicate for filtering array .
NSMutableArray *array =
[NSMutableArray arrayWithObjects:#"Nick", #"Ben", #"Adam", #"Melissa", #"arbind", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"];
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
NSArray offers another selector for sorting arrays:
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(Person *first, Person *second) {
return [first.name compare:second.name];
}];
If you want to filter array take a look on this code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"qwe"];
NSArray *result = [self.categoryItems filteredArrayUsingPredicate:predicate];
But if you want to sort array take a look on the following functions:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context hint:(NSData *)hint;
- (NSArray *)sortedArrayUsingSelector:(SEL)comparator;
visit https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html
use this
[listArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Checkout this library
https://github.com/BadChoice/Collection
It comes with lots of easy array functions to never write a loop again
So you can just do
NSArray* result = [thArray filter:^BOOL(NSString *text) {
return [[name substr:0] isEqualToString:#"A"];
}] sort];
This gets only the texts that start with A sorted alphabetically
If you are doing it with objects:
NSArray* result = [thArray filter:^BOOL(AnObject *object) {
return [[object.name substr:0] isEqualToString:#"A"];
}] sort:#"name"];

String search in string array in objective c

I want to search a specific string in the array of strings in objective c. Can somebody help me in this regard?
BOOL isTheObjectThere = [myArray containsObject: #"my string"];
or if you need to know where it is
NSUInteger indexOfTheObject = [myArray indexOfObject: #"my string"];
I strongly recommend you read the documentation on NSArray. It's best to do that before posting your question :-)
You can use NSPredicate class for searching strings in array of strings.
See the below sample code.
NSMutableArray *cars = [NSMutableArray arrayWithObjects:#"Maruthi",#"Hyundai", #"Ford", #"Benz", #"BMW",#"Toyota",nil];
NSString *stringToSearch = #"i";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",stringToSearch]; // if you need case sensitive search avoid '[c]' in the predicate
NSArray *results = [cars filteredArrayUsingPredicate:predicate];
This is the most efficient way for searching strings in array of strings
NSMutableArray *cars = [NSMutableArray arrayWithObjects:#"Max",#"Hai", #"Fine", #"Bow", #"Bomb",#"Toy",nil];
NSString *searchText = #"i";
NSArray *results = [cars filteredArrayUsingPredicate:predicate];
// if you need case sensitive search avoid '[c]' in the predicate
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"title contains[c] %#",
searchText];
searchResults = [cars filteredArrayUsingPredicate:resultPredicate];

Resources