Say I have an Entity Department that has a to-many relationship with Persons. I want to be able to search the Department Sports to see if Person Scott Olsen works there. The Person Scott Olsen is not unique (there may be 3 Scotts working in 3 different Departments).
How can I search the Department Sports to find the Person Scott Olsen that works there and not find the other Scotts?
The basic way I can think of is:
for (Person *person in sports.persons) {
if ([person.name isEqualToString:#"Scott Olsen"]) {
// found him!
}
}
Or:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY persons.name == 'Scott Olsen'"];
Department *department = [Department MR_findFirstWithPredicate:predicate];
But I'm unsure if the second returns the Scott Olsen that works in Departement Sports. I suppose I could then check
if ([department.name isEqualToString:#"Sports"])
But it seems like there should be a better way to do it with a NSPredicate, but I can't figure it out.
Is this what you are looking for?
NSString *name = #"Scott Olsen";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name = %#", name];
NSSet *filtered = [sports.persons filteredSetUsingPredicate:predicate];
Or (your question changed after I posted the above code):
NSString *name = #"Scott Olsen";
NSString *department = #"Sports";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name = %# AND department = %#",
name, department];
Person *person = [Person MR_findFirstWithPredicate:predicate];
(assuming that you have an inverse relationship "department" from Person to Department).
Just add second expression in your predicate:
[NSPredicate predicateWithFormat:#"name == 'Sports' && ANY persons.name == 'Scott Olsen'"];
Related
How do I filter an array of objects by a specific field?
My code:
NSMutableArray *inputArray = [[NSMutableArray alloc]init];
Person *person = [[Person alloc]init];
person.first_name = #"John";
[inputArray addObject: person];
person = [[Person alloc]init];
person.first_name = #"Jack";
[inputArray addObject: person];
NSString *expression = [NSString stringWithFormat:#"SUBQUERY(inputArray, $object, $object.first_name CONTAINS[c] J"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression];
NSMutableArray *filteredArray = [[inputArray filteredArrayUsingPredicate:predicate]mutableCopy];
NSLog(#"Count should be 2: %lu",(unsigned long)filteredArray.count);
This is the error I get:
'NSInvalidArgumentException', reason: 'Unable to parse the format string "SUBQUERY(inputArray, $object, $object.first_name CONTAINS[c] J"'
This is a basic example for testing. The real-case scenario is that I have an array of objects (Person or whatever) and I want to filter that array by certain fields within the objects ie first_name. As the user types we will filter a visual list based on what they type - so typing "J" would yield 2 results, but then when they type "Jo" only "John" appears on the list.
What am I doing wrong?
EDIT
Still doesn't seem to be working. Updated code:
DOVisitor *vi = [inputArray objectAtIndex:0];
NSLog(#"NAME: %#",vi.first_name);
NSPredicate *firstNamePredicate=[NSPredicate predicateWithFormat:#"first_name LIKE[cd] %#", #"Jo"];
NSPredicate *lastNamePredicate =[NSPredicate predicateWithFormat:#"last_name LIKE[cd] %#", #"Jo"];
NSPredicate *finalPredicate = [NSCompoundPredicate orPredicateWithSubpredicates : #[firstNamePredicate, lastNamePredicate]];
NSArray *filteredArray = [[inputArray filteredArrayUsingPredicate:finalPredicate]mutableCopy];
NSLog(#"Count should be 1: %d", [filteredArray count]);
I get an empty array back. However when I print the first object of the inputArray the console logs "John"
EDIT
Using CONTAINS instead of LIKE does the trick
You don't need a subquery for this, this is a very basic filter.
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"first_name CONTAINS[cd] %#", #"j"];
Let us say you have Person object and you are trying to search for both firstName and lastName, then you can use:
NSPredicate *firstNamePredicate=[NSPredicate predicateWithFormat:#"firstName LIKE[cd] %#", #"Jo"];
NSPredicate *lastNamePredicate =[NSPredicate predicateWithFormat:#"lastName LIKE[cd] %#", #"Jo"];
NSPredicate *finalPredicate = [NSCompoundPredicate orPredicateWithSubpredicates : #[firstNamePredicate, lastNamePredicate]];
The final Predicate is generated by oring the previous predicates. So even if Jo is present in firstName or lastName, that Person object will pass the predicate test.
Edit:
Get filtered objects with above predicate
NSArray *filteredArray = [inputArray filteredArrayUsingPredicate:finalPredicate];
I have an entity called "Contact", Every contact as a category property that holds a string with category name. I wish to fetch only contacts from few of the categories.
For example I have few entities:
contact1.category = #"a";
contact2.category = #"b";
contact3.category = #"c";
contact4.category = #"c";
contact5.category = #"a";
Then I have this array of active categories:
self.selectedCategories = #[#"b",#"c"];
Now I want to fetch from core data only entities from #"a" and #"b".
Is that possible with an NSPredicate to pass to the fetch request?
Thanks
Shani
This will help you!
NSPredicate *inPredicate = [NSPredicate predicateWithFormat: #"category IN %#", aCollection];
[request setPredicate:predicate];
I have an app using coreData fine.
I have this relationship:
company <--->> visitors
now, I need to find specific visitors for an specific company, I can fetch visitors starting with some string pattern,
But how to find the ones for a specific company?
here my code
- (void)searchAvailableDataFullName:(NSTimer*)timer
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fullName BEGINSWITH [c] %#",self.nameTF.text];
//sort descriptor!
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"fullName" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
//the relationship of interest??
Visitor *theVisitor = nil;
theVisitor.company = self.selectedCompany;
NSMutableArray *fullNamesArray = [NSMutableArray arrayWithArray:[Visitor allWithPredicate:predicate sortDescriptors:#[sortDescriptor]]];
Visitor *visitorName;
NSMutableArray *dataArray = [NSMutableArray array];
for (visitorName in fullNamesArray) {
NSLog(#"tus visitors:: %#", visitorName.fullName);
[dataArray addObject:visitorName.fullName];
}
}
I don't have my Mac in front of me atm but it should be something like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"visitors.fullName BEGINSWITH [c] %# && visitors.CompanyName BEGINSWITH [c] %#",self.nameTF.text, companyNameTextObject];
Hope that's 100% right, if not you can kind of get the gist of it. You can use the "table.relationshipProperty" to search the relationship.
Apple Predicate Programming Guide
There's some more info there, just check out the "Joins" section. Hope that helps!
I need to sort my fetch request with selected people, but it doesn't return anything
I tried this code with coredata objects comparing
NSPredicate *peoplePredicate = [NSPredicate predicateWithFormat:#"SUBQUERY(classPeople, $p, $p IN %#).#count == %d", self.selectedPeople, [self.selectedPeople count]];
and this with nsnumber iD comparing
NSPredicate *peoplePredicate = [NSPredicate predicateWithFormat:#"SUBQUERY(classPeople, $p, $p.iD IN %#).#count == %d", self.selectedPeopleiD, [self.selectedPeopleiD count]];
I have entity class, which has relationship people. And I have viewcontroller where I can select some people in list, after selecting people objects are adding to array self.selectedPeople, so I need to fetch all objects of Class entity, which has selected people
thanks in advance
So, then your predicate should look like:
NSPredicate *peoplePredicate = [NSPredicate predicateWithFormat:#"ANY classPeople IN %#", self.selectedPeople];
Hey i want to filter an NSArray. In this Array is a lot of information like name, town, telephonenumber, and so on. But some towns are twice or three times in the array.
I have property with a town in it.
So i want only those objects from the arry which match with the property.
For example:
in the Array stands:
Frank, New York, 123456
Oliver, New York, 123456
Thomas, Boston, 123456
and when the property is New York i want olny objects 1 and 2.
Does anyone has an idea how i can do it?
This is my code:
NSString *filterString = newsArticle;
NSPredicate *prediacte = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"Ort == '%#'",filterString]];
newsTownArray = [news filteredArrayUsingPredicate:predicate];
and when i come to the line:
cell.textLabel.text=[[newsTownArray objectAtIndex:indexPath.row] objectForKey:"Name"];
You need to use NSPredicate for this.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"town == 'New York'"];
[yourArray filterUsingPredicate:predicate];
Dynamically you can create predicate like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"town == '%#'",yourInput]];
Here yourInput is a NSString which holds the required town name.
Please check these articles for more details:
codeproject
useyourloaf
Use this code
NSMutableArray *subpredicates = [NSMutableArray array];
for(NSString *term in arryOfWordsToBeSearched) {
NSPredicate *p = [NSPredicate predicateWithFormat:#"self contains[cd] %#",term];
[subpredicates addObject:p];
}
NSPredicate *filter = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
result = (NSMutableArray*)[arryOfDummyData filteredArrayUsingPredicate: filter];
However you can do it within an array with the use of NSPredicate, but I will suggest to do bit differently, this will add up to your code and good programming way.
Create a custom class Person having these properties name, city and telephone.
Create an array that will store objects of Person.
After this you can manipulate/ filter / sort etc quite easily.
NSString *filterCity=#"Delhi";
NSMutableArray *yourArray=[NSMutableArray arrayWithArray:self.persons];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"city == '%#'",filterCity]];
[yourArray filterUsingPredicate:predicate];
NSLog(#"Filtered");
for (Person *per in yourArray) {
NSLog(#"Name: %#, City: %#, Telephone: %#",per.name, per.city, per.telephone);
}