Searching an Array using NSPredicate method predicateWithFormat - ios

Currently trying to setup a search would search an Array (bakeryProductArray) which looks like this
"Tea Loaf",
Tiramusu,
"Treacle Loaf",
Trifle,
"Triple Chocolate Brownie",
Truffles,
"Various sponges",
"Viennese Whirls",
"Wedding Cakes"
with what the users types into the UISearchbar. I am unclear on how to represent each item in the array in the CFString.
The code I currently have is.
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope
{
searchSearch = [NSPredicate predicateWithFormat:#"self CONTAINS[cd]",searchText];
//#"%K CONTAINS[cd] %#"
searchResults = [bakeryProductArray filteredArrayUsingPredicate:searchSearch];
NSLog(#"Filtered Food Product Count --> %d",[searchResults count]);
}
Can answer any questions and supply more code if needed.

Is this what your are looking for?
NSArray *bakeryProductArray = #[#"Tea Loaf", #"Tiramusu", #"Treacle Loaf", #"Trifle"];
NSString *searchText = #"tr";
NSPredicate *searchSearch = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", searchText];
NSArray *searchResults = [bakeryProductArray filteredArrayUsingPredicate:searchSearch];
NSLog(#"%#", searchResults);
// "Treacle Loaf",
// Trifle
This finds all strings that contain the given search string (case insensitive).
Alternatively, you can use "=" or "BEGINSWITH", depending on your needs.
(More information about predicates in the "Predicate Programming Guide" .)

Related

Filter NSArray of Arrays by One Element of Array Using NSPredicate in IOS

It is possible to filter an array of strings as follows:
NSArray *array = #[#"honda",#"toyota",#"ford"];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#",#"ford"];
NSArray *filtered = [array filteredArrayUsingPredicate:pred];
I want to search an array that contains arrays of two strings by the values for the first of the strings. So for:
NSArray *cars = #[#[#"honda",#"accord"],#[#"toyota",#"corolla"],#[#"ford",#"explorer"]];
I want to search the first dimension (honda, toyota, ford) for #"ford"
Is there a way to tell the predicate I want to search on only the first attribute and return matching elements of the array?
Well here is the pred you need.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF[FIRST] contains[cd] %#", #"ford"];

UISearchDisplayController with more than one search term

I wonder if there is any way to search for more than one word using UISearchDisplayController? If I for example want to search for posts containing both "James" AND "London"? Or "James" and "Smith"?
I have searched but not found an answer to this.
This is what I do now, to see if the search term is in either the name or address.
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSMutableArray *searchItemsPredicate = [NSMutableArray array];
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
[searchItemsPredicate addObject:namePredicate];
NSPredicate *addressPredicate = [NSPredicate predicateWithFormat:#"address contains[c] %#", searchText];
[searchItemsPredicate addObject:addressPredicate];
NSCompoundPredicate *combinedPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
searchResults = [_array filteredArrayUsingPredicate:combinedPredicate];
}
A possible solution would be to separate each words.
You can use a NSRegularExpression or use simply componentsSeparatedByString: (to keep it simple).
NSArray *words = [searchText componentsSeparatedByString:#" "];
NSMutableArray *allPredicates = [[NSMutableArray alloc] init];
for (NSString *aWord in words)
{
NSPredicate *addressPred = [NSPredicate predicateWithFormat:#"address contains[c] %#", aWord];
NSPredicate *namePred = [NSPredicate predicateWithFormat:#"name contains[c] %#", aWord];
[allPredicates addObject:addressPred];
[allPredicates addObject:namePred];
}
NSCompoundPredicate *finalPredicate = [[NSCompoundPredicate alloc] initWithType: NSOrPredicateType subPredicates:allPredicates];
searchResults = [_array filteredArrayUsingPredicate: finalPredicate];
You can use a more complexe scheme for your "words limitations" (comma, etc.) to mark delimitations for example:
Searching #"Banana, Apple fruit" could be in fact looking for "words" : #"Banana" and #"Apple fruit", in that case the separator string would be "," (and you may have to trim for white spaces).

How to filter a NSArray

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

NSPredicate and BeginsWith

I would like to figure out the NSPredicate that will search my Core data for words that begins with:
For example:
description field in the core data has text like this:
My name is Mike
My name is Moe
My name is Peter
My name is George
If I search 'My name is' I need to get the 3 lines
If I search 'My name is M' I need to get the first 2 lines
I tried the code below, but can't get what I need. My guess I need a regular expression, but not sure how to do it.
[NSPredicate predicateWithFormat:#"desc beginswith [cd] %#",word];
I did it this way recently and worked fine. Try it out. I see I don't have [cd] and beginswith but contains. You could give it a try.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains %#", textField.text];
NSArray *list = [allWords filteredArrayUsingPredicate:predicate];
for(NSString *word in list){
NSLog(#"%#",word);
}
After reading the comments on the starting post:
First of all, you should split up the words in the string from the textfield:
NSArray *myWords = [textField.text componentsSeparatedByString:#" "];
Then doing the same like you first would:
for(NSString *wordFromTextField in myWords){
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains %#", wordFromTextField];
NSArray *list = [allWords filteredArrayUsingPredicate:predicate];
for(NSString *word in list){
NSLog(#"%#",word);
}
}
Instead of NSLogging the words you could add them to an array of course.

How to filter array with NSPredicate for combination of words

[filteredArray filterUsingPredicate:
[NSPredicate predicateWithFormat:#"self BEGINSWITH[cd] %#", searchText]];
filteredArray contains simple NSStrings. [hello, my, get, up, seven, etc...];
It will give all strings that begin with searchText.
But if string will be a combination of words like "my name is", and searchText = name. What would a NSPredicate look like to achieve this?
UPDATE:
And how would it have to be if i want to a result with searchText = name, but not with searchText = ame? Maybe like this:
[filteredArray filterUsingPredicate:
[NSPredicate predicateWithFormat:
#"self BEGINSWITH[cd] %# or self CONTENTS[cd] %#",
searchText, searchText]];
But it should first display the strings that begin with searchText and only after those which contain searchText.
[NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", searchText];
EDIT after expansion of question
NSArray *beginMatch = [filteredArray filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:
#"self BEGINSWITH[cd] %#", searchText]];
NSArray *anyMatch = [filteredArray filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:
#"self CONTAINS[cd] %#", searchText]];
NSMutableArray *allResults = [NSMutableArray arrayWithArray:beginMatch];
for (id obj in anyMatch) {
if (![allResults containsObject:obj]) {
[allResults addObject:obj];
}
}
filteredArray = allResults;
This will have the results in the desired order without duplicate entries.
EDIT Actually beginsWith check from start of string to search string length. if exact match found then its filtered
if u have name game tame lame
search Text : ame
filtered text would be: none
contains also check from start of string to search string length but if found start, middle or end exact search string then it is filtered.
if u have name game tame lame
search Text : ame
filtered text would be: name game tame lame because all has ame
[NSPredicate predicateWithFormat:#"self CONTAINS '%#'", searchText];

Resources