问题
I tried to build a predicate in a previous post, but ended up doing it this way because after 3 hours, I couldn't get it to work.
I feel like there has to be a more effective way, also I need the predicates to be case insensitive.
10,000 cars I have a tire, wheel, seat as three car parts I want to find all cars that have a tire. THEN I want to find all cars that have a wheel. THEN I want to find all cars that have a seat. (I know many will be duplicates, but that's what I need)
Please let me know if there is a more effective way. Also please let me know how to make the predicates case insensitive.
Thank you in advance!
-(NSArray*) loadCarsFromCoreData:(NSMutableArray*)inputCarParts{
NSMutableArray *totalResults=[[NSMutableArray alloc]init];
NSFetchRequest *fetchRequest =[[NSFetchRequest alloc]init];
//To find the cars we are using the car parts
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CarParts" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *predicates =[self parseCarPartsIntoAPredicateArray:inputCarParts];
for (int i=0; i<[predicates count]; i++) {
[fetchRequest setPredicate:[predicates objectAtIndex:i]];
NSArray *records = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
NSLog(@"results = %i",[records count]);
[totalResults addObjectsFromArray:records];
}
NSLog(@"results = %i",[totalResults count]);
return [NSArray arrayWithArray:totalResults];
}
-(NSMutableArray*)parseCarPartsIntoAPredicateArray:(NSMutableArray*)inputCarParts{
NSMutableArray *returnArray=[[NSMutableArray alloc]init];
for (int i=0; i<[inputCarParts count]; i++) {
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"partName == %@",[inputCarParts objectAtIndex:i]];
[returnArray addObject:predicate];
}
return returnArray;
}
回答1:
It sounds like what you're really looking for is how to construct a predicate based on an array of possible matches. In that case you'd do something like this:
NSMutableArray *partPredicates = [NSMutableArray arrayWithCapacity:[inputCarParts count]];
for (NSString *partName in inputCarParts) {
NSPredicate *currentPartPredicate = [NSPredicate predicateWithFormat:@"partName =[c] %@", partName];
[partPredicates addObject:currentPartPredicate];
}
NSPredicate *fullPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:partPredicates];
The resulting predicate would then be something like partName ==[c] "tire" OR partName ==[c] "wheel" OR partName ==[c] "seat"
, with one component per array entry. Do one fetch to evaluate them all in one shot.
This will not get duplicate results if you use it in the fetch. You left a comment on the question that indicates you don't want duplicates. If that's the case though, then I'm not sure what I know many will be duplicates, but that's what I need means. It sounds like you wanted the dupes, but you said you didn't.
回答2:
If you need the duplicates, I think you'll have to do 3 separate queries like you're currently doing.
If the duplicates aren't important, you should try creating a compound predicate by using OR
between the three predicates you need. The following will find all the cars that either have the specified wheel, tire, or seat:
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"wheelPartName == %@ OR tirePartName == %@ OR seatPartName == %@", wheelPart, tirePart, seatPart];
To make your searches case insensitive, use ==[c]
instead of ==
, so the predicate in your code would look like:
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"partName ==[c] %@",[inputCarParts objectAtIndex:i]];
Take a look at this reference: String Predicate Programming.
来源:https://stackoverflow.com/questions/14126766/most-effective-way-of-searching-using-nspredicate-or-statement