Predicate in array - iphone

I have an array which contains lots of info like lat,lon,city name etc.But all this info stored by class object.
("<GetCityList: 0x1fd334d0>",
"<GetCityList: 0x1fd33560>",
"<GetCityList: 0x1fd33310>",)
my array is looking like this.if i want city name then first i create GetCityList object and then object.cityName.
Now i have to search lat and lon by comparing cityName.so how can i do,because it consumes too much time?can i use predicate ?how?

Let say you have an array of cityList and want to Filter this by city name you can do
NSPredicate *cityNamePredicate = [NSPredicate predicateWithFormat:#"cityName contains[c] %#", #"cityName"]
NSArray *filteredCityList = [cityList filteredArrayUsingPredicate:cityNamePredicate];
Above filteredCityList will be your required filtered array whatever you passed in parameter. Here [cd] means case and diatric insensitive
You can refer this tutorial for further exploring NSPredicate.

Example:
self.data = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"To Airport",#"TO/AIR", nil] forKeys:[NSArray arrayWithObjects:kName,kCode, nil]],
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"Point-to-Point",#"PTP", nil] forKeys:[NSArray arrayWithObjects:kName,kCode, nil]],[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"From Airport",#"FR/AIR", nil] forKeys:[NSArray arrayWithObjects:kName,kCode, nil]], nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(name CONTAINS[cd] %#)",searchText];
self.searchableData = [self.data filteredArrayUsingPredicate:predicate];
Based on this you can replace name with cityName.

Use it in this way also:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"cityName contains %#", #"cityNamehere"]
NSMutableArray *filtered = [cityListArray filterUsingPredicate:predicate];

Related

Search NSArray using NSPredicate

I am new to NSPredicate so sorry if I am asking stupid question. I have two NSArray (keyArray and valueArray). I have to find match in valueArray using keyArray. Below code is working fine but I have to search one by one. Any way to search an array using a different key array.
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"companyId = %#", [[[self selectedCompanies] objectAtIndex:0] companiesIdentifier]];
NSLog(#"Users: %#", [[[self userData] users] filteredArrayUsingPredicate:userPredicate]);
NSPredicate *userPredicate1 = [NSPredicate predicateWithFormat:#"companyId = %#", [[[self selectedCompanies] objectAtIndex:1] companiesIdentifier]];
NSLog(#"Users: %#", [[[self userData] users] filteredArrayUsingPredicate:userPredicate1]);
You can do:
NSPredicate *userPredicate1 = [NSPredicate predicateWithFormat:#"companyId IN %#", [[self selectedCompanies] valueForKey:#"companiesIdentifier"];
NSLog(#"Users: %#", [[[self userData] users] filteredArrayUsingPredicate:userPredicate1]);
What happens here is we take the companiesIdentifier of all selected companies and match users based on those identifiers.
valueForKey: on an array object returns an array with the value of the required key for each object in the array. IN is a predicate operator searching in a collection (array, set, etc.).

NSPredicate using OR error

First time building an NSPredicate.
I would like to search a managedobjectcontext using this logic:
Search for a, grab all matches
Search for b, grab all matches, etc....
Nsarray *results = (has all a results, b results, etc);
My attempted predicate is:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name== %# OR name == %# OR name == %#",a,b,c];
However I get errors with this predicate...
Edited: Sample method I wrote
-(NSPredicate*)parsePartsIntoAPredicate:(NSMutableArray*)inputPartsNames{
NSSet *keys=[NSSet setWithArray:inputPartsNames];
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"any self.#name in %#", keys];
NSLog(#"predicate = %#",predicate);
return predicate;
}
Clarify: I have a database of cars (20,000) Each car has multiple parts. I want to find all cars that have part a, and all cars that have part b, and all that have part c. Then I want to return an array with cars with part a, b, c, etc...
If you think there is a better way let me know, but I am approaching this backwards. I am saying
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Cars" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[self parsePartsIntoAPredicate:inputParts]];
NSError *error;
NSArray *records = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
What am I doing wrong?
NSString *key;
NSMutableArray *tempArray;
NSPredicate *searchForName = [NSPredicate predicateWithFormat:#"name = %#", key];
NSArray *filterArray = [tempArray filteredArrayUsingPredicate:searchForName];
NSLog(#"%#",filterArray);
Where key is your searchKeyword, tempArray is your CompleteArray in which data is present.
Use Like this. Please put your data.
Use this
NSPredicate* predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"%# '%#'", #"SELF contains[c] ",searchText]];
To fetch all Cars objects that have a name which is one of the strings in the keys set or array, use
[NSPredicate predicateWithFormat:#"name IN %#", keys]

NSPredicate filter

I have never used NSPredicate before so please bear with me. I have an array which have a boolean key as "isChecked". I want to filter the array which have the boolean set as "YES", any idea how can I do it, plus if there is any reference to such query methods that would be nice to have it handy.
Thanks
//NSArray * myArray is your array
//containing your objects that each have an isChecked property
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isChecked == YES"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
// filteredArray is the new array that only contains your checked items
Cheers
First you create an NSPredicate instance. In this case, we'll use -initWithFormat:.
NSPredicate *predicate = [[NSPredicate alloc] initWithFormat:#"isChecked == YES"];
Then we'll use the -filteredArrayUsingPredicate: method on NSArray to get an NSArray of all the objects which match the predicate.
NSArray *filteredArray = [originalArray filteredArrayUsingPredicate:predicate];

fetching objects from core data not in a set

I'm trying to fetch objects from core data that are not in a given set, but I haven't been able to get it to work.
For instance, suppose that we have a core data entity named User, which has a few attributes such as userName, familyName, givenName, and active. Given an array of strings representing a set of usernames, we can easily fetch all the users corresponding to that list of usernames:
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User"
inManagedObjectContext:moc];
[request setEntity:entity];
NSArray *userNames = [NSArray arrayWithObjects:#"user1", #"user2", #"user3", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"userName IN %#", userNames];
[request setPredicate:predicate];
NSArray *users = [moc executeFetchRequest:request error:nil];
However, I want to fetch the complement of that set, i.e., I want all the users in core data that don't have the usernames specified in the userNames array. Does anyone have an idea how to approach this issue? I thought it would be simple enough to add a "NOT" in the predicate (i.e., "userName NOT IN %#"), but Xcode throws an exception saying the predicate format could not be parsed. I also tried using the predicate builder available for fetch requests with no luck. The documentation wasn't particularly helpful either. Suggestions? Comments? Thanks for all your help :)
In order to find the objects that aren't in your array, all you have to do is something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (userName IN %#)", userNames];
That should return a request of all the objects without the ones you specified
I am not strong at core data/objective-c but the predicate should be like the following statement;
[predicateFormat appendFormat:#"not (some_field_name in {'A','B','B','C'})"];
An example:
NSMutableString * mutableStr = [[NSMutableString alloc] init];
//prepare filter statement
for (SomeEntity * e in self.someArray) {
[mutableStr appendFormat:#"'%#',", e.key];
}
//excluded objects exist
if (![mutableStr isEqual:#""])
{
//remove last comma from mutable string
mutableStr = [[mutableStr substringToIndex:mutableStr.length-1] copy];
[predicateFormat appendFormat:#"not (key in {%#})", mutableStr];
}
//...
//use this predicate in NSFetchRequest
//fetchRequest.predicate = [NSPredicate predicateWithFormat:predicateFormat];
//...
Here's another useful example, showing how to take a list of strings, and filter out any which DON'T start with the letters A-Z:
NSArray* listOfCompanies = [NSArray arrayWithObjects:#"123 Hello", #"-30'c in Norway", #"ABC Ltd", #"British Rail", #"Daily Mail" #"Zylophones Inc.", nil];
NSPredicate *bPredicate = [NSPredicate predicateWithFormat:#"NOT (SELF MATCHES[c] '^[A-Za-z].*')"];
NSArray *filteredList = [listOfCompanies filteredArrayUsingPredicate:bPredicate];
for (NSString* oneCompany in filteredList)
NSLog(#"%#", oneCompany);
I use this kind of NSPredicate when I'm populating a UITableView with an A-Z index, and want an "everything else" section for items which don't start with a letter.

Does CoreData on iPhone support IN predicates?

I'm trying to fetch a bunch of records of a certain type, based on a list of types defined by the user…
[fetchRequest setEntity:[NSEntityDescription entityForName:#"myRecord" inManagedObjectContext:self.managedObjectContext]];
NSSet *shipTypes = [NSSet setWithObjects:[NSNumber numberWithInt:70],
[NSNumber numberWithInt:71],
[NSNumber numberWithInt:72],
[NSNumber numberWithInt:73],
[NSNumber numberWithInt:74],
nil];
NSPredicate *aPredicate = [NSPredicate predicateWithFormat:#"type in %#", shipTypes];
[fetchRequest setPredicate:aPredicate];
theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
…when run, the executeFetchRequest message throws an exception…
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unimplemented SQL generation for predicate : (type IN {71, 73, 70, 72, 74})'
Have I done something wrong, or is this really not supported?
I believe Alex is right that you have to use an NSArray, although obviously it'd be nicer if NSSet were accepted here, since order isn't that important (although it could conceivably affect how quickly the SQL can run).
As a side note, I never use the +predicateWithFormat: call in any code, ever, because it can't do compile-time sanity or type-checking. I highly advise using the individual classes.
In this case, I'd do:
fetchRequest.entity = [NSEntityDescription entityForName:#"myRecord" inManagedObjectContext:self.managedObjectContext]];
NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
[NSNumber numberWithInt:71],
[NSNumber numberWithInt:72],
[NSNumber numberWithInt:73],
[NSNumber numberWithInt:74],
nil];
fetchRequest.predicate = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:#"type"] rightExpression:[NSExpression expressionForConstantValue:shipTypes] modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0];
theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
Not that this would have caught this particular error at compile time, but it WOULD have potentially caught it at the NSExpression level, thus making it much clearer what went wrong.
Hmm. I tried both adding the ANY keyword and using NSArray. Actually I was using NSAArray to start with when I got this exception from Core Data. In retrospect think that because I was combining two expressions with AND it was a problem for Core Data. (I know I should go back and verify this but this thought just occurred to me, while reading this post.) Here is my original expression:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"BPM BETWEEN { %d, %d } AND GENRE IN %#", lower, upper, genres];
My solution was to break it up into two parts. Now, I issue the query for the BPM using the predicate but I take the resulting array and use -filteredArrayUsingPredicate with #"genre IN %#". Thus:
array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"genre IN %#", genres]];
This works for me.
I struggled with this. Eventually I ended up doing a sub predicate for each of the set.
So for example:
NSMutableArray *subpredicates = [NSMutableArray array];
NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
[NSNumber numberWithInt:71],
[NSNumber numberWithInt:72],
[NSNumber numberWithInt:73],
[NSNumber numberWithInt:74],
nil];
for (NSNumber *num in shipTypes) {
[subpredicates addObject:[NSPredicate predicateWithFormat:#"ANY type == %#", num]];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
That's assuming that type is a NSSet. If it's not you could just have:
for (NSNumber *num in shipTypes) {
[subpredicates addObject:[NSPredicate predicateWithFormat:#"type == %#", num]];
}
Try changing your predicate to #"ANY type IN %#"