How to implement searching of a string in an array of dictionaries? - iphone

I have an application in which i have an nsmutable array created like this .`
NSDictionary *memberInfo = [self.currentChannel infoForMemberWithID:memberID];
for(int i=0;i<self.currentChannel.memberCount;i++)
{
[searchfriendarray addObject:memberInfo];
}
NSLog(#"dfdfdfsear%#",searchfriendarray);
The response i am getting is this
dfdfdfsear(
{
name = baddd;
status = "<null>";
},
{
name = baddd;
status = "<null>";
}
)
`
Now i want to search an nsstring in this.with the method
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
Can anybody help me in implementing the search and load my tableview according to that?

Use NSPredicate to filter the array.
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"name contains[cd] %#", searchString];
[yourMutableArray filterUsingPredicate:filterPredicate];

You can use NSPredicate for this.
Predicate
A predicate is a useful object that filters an array. It’s a bit like having a select with a simple where clause in SQL.
If you have array in this format
NSMutableArray *yourAry;
(
{
category = classic;
quote = "Frankly, my dear, I don't give a damn.";
source = "Gone With the Wind";
},
{
category = classic;
quote = "Here's looking at you, kid.";
source = Casablanca;
}
{
category = modern;
quote = "I solemnly swear that I am up to no good.";
source = "Harry Potter and the Prisoner of Azkaban";
},
{
category = modern;
quote = "You like pain? Try wearing a corset.";
source = "Pirates of the Caribbean";
}
)
And you want to search all the array which category = classic then we can use NSPredicate.
NSString *selectedCategory = #"classic";
//filter array by category using predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"category == %#", selectedCategory];
NSArray *filteredArray = [self.movieQuotes filteredArrayUsingPredicate:predicate];
Follow this blog if you need any help MyBlog

Related

NSPredicate match any characters

How do I construct an NSPredicate that looks for the search terms anywhere in an Arrays objects? I can't quite explain it properly, so here's an example.
NSArray *array = #[#"Test String: Apple", #"Test String: Pineapple", #"Test String: Banana"];
NSString *searchText = #"Apple";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS[cd] %#", searchText];
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate];
NSLog(#"filteredArray: %#", filteredArray);
// filteredArray: (
// "Test String: Apple",
// "Test String: Pineapple"
// )
But if I use NSString *searchText = #"Test Str Appl"; I get zero results. I'd like it to match the same results for this string.
What I'm looking for is a search function that is similar to the "Open Quickly" menu in Xcode, where it doesn't matter if your search string is worded correctly, only that the letters are in the correct order as a match. I really hope that makes sense.
The LIKE string comparison in predicates allows for wildcards * and ?, where * matches 0 or more characters. Therefore, if you transform your search text into
NSString *searchWithWildcards = #"*T*e*s*t* *S*t*r*A*p*p*l*";
by inserting a * at the beginning, between all characters, and at the end of the original search text by using something like this
NSMutableString *searchWithWildcards = [NSMutableString stringWithFormat:#"*%#*", self.searchField.text];
if (searchWithWildcards.length > 3)
for (int i = 2; i < self.searchField.text.length * 2; i += 2)
[searchWithWildcards insertString:#"*" atIndex:i];
then you can use
[NSPredicate predicateWithFormat:#"SELF LIKE[cd] %#", searchWithWildcards];
The predicate searches for the characters in the given order, with arbitrary other characters between them.
The transformation can for example be done with the following code:
NSMutableString *searchWithWildcards = [#"*" mutableCopy];
[searchText enumerateSubstringsInRange:NSMakeRange(0, [searchText length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[searchWithWildcards appendString:substring];
[searchWithWildcards appendString:#"*"];
}];
Because I can't read objcC that good, I wrote my own wildcard function. Here we go:
Swift 5
CoreData is fetched into initialized array
var originalArray: [NSManagedObject] = []
extension myViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
filteredArray.removeAll(keepingCapacity: true)
if searchController.searchBar.text!.isEmpty {
filteredArray = originalArray
} else {
let filter = searchController.searchBar.text!
var filterWithWildcards = ""
for i in 0 ..< filter.length {
if i == 0 {
filterWithFormat = "*"
}
filterWithFormat += filter[i] + "*"
}
print("filter: \(filter); filterWithWildcards: \(filterWithWildcards)") // filter: Mxmstrmnn; filterWithFormat: *M*x*m*s*t*r*m*n*n*
myPredicate = NSPredicate(format: "EnterYourAttributeNameOfCoreDataEntity LIKE[c] %#", filterWithWildcards)
let array = (people as NSArray).filtered(using: myPredicate!)
filteredArray = array as! [NSManagedObject]
}
myTableView.reloadData()
}}
The result in filteredArray finds Max Mustermann as long as I keep the order of letters.
To get the index letter of filter[i], I use a String extension from here https://stackoverflow.com/a/26775912/12035498
Thanks to Martin R
There is my swift5 version
let wildcardSting = "*" + text.map { "\($0)*" }.joined()
let predicate = NSPredicate.init(format: "%K LIKE[cd] %#", #keyPath(Record.name), wildcardSting)

Objective C: Filter out results from NSMutableArray by a dictionary key's value?

I have a NSMutableArray like this :
(
{
City = "Orlando";
Name = "Shoreline Dental";
State = Florida;
},
{
City = "Alabaster ";
Name = Oxford Multispeciality;
State = Alabama;
},
{
City = Dallas;
Name = "Williams Spa";
State = Texas;
},
{
City = "Orlando ";
Name = "Roast Street";
State = Florida;
}
)
Now how can I sort this NSMutableArray to get the results corresponding to State "Florida"
I expect to get
(
{
City = "Orlando";
Name = "Shoreline Dental";
State = Florida;
},
{
City = "Orlando ";
Name = "Roast Street";
State = Florida;
}
)
I went for this code,but it displays again the prevous four dictionaries .
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Florida" ascending:YES];
NSArray * descriptors = [NSArray arrayWithObject:valueDescriptor];
NSArray * sortedArray = [arr sortedArrayUsingDescriptors:descriptors];
Try using a comparator block:
NSIndexSet *indices = [array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [[obj objectForKey:#"State"] isEqualToString:#"Florida"];
}];
NSArray *filtered = [array objectsAtIndexes:indices];
Alternatively, you can use a predicate as well:
NSPredicate *p = [NSPredicate predicateWithFormat:#"State = %#", #"Florida"];
NSArray *filtered = [array filteredArrayUsingPredicate:p];
If your array contains dictionary then you can use NSPredicate to filter out your array as follows:
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"State CONTAINS[cd] Florida"];
theFilteredArray = [theArray filteredArrayUsingPredicate:thePredicate];
Assuming your array name is : arr
This one of the typical way to find, although a bit obsolete way....
for (NSDictionary *dict in arr) {
if ([[dict objectForKey:#"State"]isEqualToString:#"Florida"]) {
[filteredArray addObject:dict];
}
}
NSLog(#"filteredArray->%#",filteredArray);
Using predicates and blocks are already posted :)
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"State = %#", #"Florida"];
NSArray *filteredArray = [arr filteredArrayUsingPredicate:predicate];
NSLog(#"filtered ->%#",filteredArray);

NSPredicate doesn't filter data for long value in iOS 5

I am trying to filter data from array using NSPredicate.
My array (arrLikes) contains following data from server
{
"id":17,
"likes":[
{
"likedBy":
{
"firstName":"Bob",
"lastName":"Builder",
"id":1
}
}],
"comments":[]
}
I am trying to filter the data from array like below
long loggedInUserId = [[dictUserInfo objectForKey:#"id"] longValue];
NSPredicate *likePredicate = [NSPredicate predicateWithFormat:#"id == %ld", loggedInUserId ];
NSArray *filteredLikeArray = [arrLikes filteredArrayUsingPredicate:likePredicate];
Even if my loggedInUserId is 1 , filteredLikeArray count retruns 0.
What wrong in above code ?
Any kind of help is appreciated. Thanks.
Did you try converting long into NSString as follows?
long loggedInUserId = 17;
NSString *stringUserId = [NSString stringWithFormat:#"%ld", loggedInUserId];
NSPredicate *likePredicate = [NSPredicate predicateWithFormat:#"id == %#", stringUserId];
NSArray *filteredLikeArray = [arrLikes filteredArrayUsingPredicate:likePredicate];

NSArray empty with filteredArrayUsingPredicate ios

i have a little problem with "predicate"
i have NSArray (datesArray) which is composed to :
(
"2011-11-30",
"2011-11-28",
"2011-11-25"
)
and another NSArray (leadsArray) which composed to :
(
{
"date_deadline" = "2011-11-30";
name = "test1";
};
{
"date_deadline" = "2011-11-28";
name = "test2";
};
{
"date_deadline" = "2011-11-25";
name = "test3";
};
{
"date_deadline" = "2011-11-28";
name = "test4";
};
)
then i do that :
NSString *date = [datesArray objectAtIndex:section];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"date beginswith %#", date];
NSArray *leads = [leadsArray filteredArrayUsingPredicate:predicate];
return [leads count];
But my NSAraay (leads) is empty.
I do that to know the "numberOfRowsInSection".
Can you help me please?
As the key for the dates in your dictionary is "date_deadline" it should at least read
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"date_deadline beginswith %#", date];
In any case consider if you needs beginswith or can test for equal and if you need to store strings for dates or can use NSDate objects.

Core Data Query Multiple Columns with Single Search String

I have a simple Core Data model with two string attributes (size and category). Given a search string like 'small widget' is it possible to return records that match all the query words to at least one attribute (i.e. all records with 'small' size and 'widget' category)? I currently have:
NSString *search = #"small widget"
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"size contains[cd] %# OR category contains[cd] %#", search, search];
...
This won't return any results (as no category or size equals "small widget"). Any suggestions? Note that the search strings will be user entered from a text field and may come in any order so I can't split up manually.
I haven't tested it but it looks like your want this:
NSString *search = #"small widget";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%# contains[cd] size AND %# contains[cd] category", search, search];
The search string would contain (or not) the size and the category, you should ask if the current size or category is contained on the search string.
You could also split the search string and modify your predicate. You should them to identify the one that performs better
NSString *search = #"small widget";
NSArray *array = [search componentsSeparatedByString:#" "];
NSMutableArray *subPredicates = [NSMutableArray array];
for (NSString *q in array) {
[subPredicates addObject:
[NSPredicate predicateWithFormat:#"size contains[cd] %# OR category contains[cd] %#", q, q]];
}
NSCompoundPredicate *predicate = [[[NSCompoundPredicate alloc] initWithType:NSAndPredicateType
subpredicates:subPredicates] autorelease];
For Swift you can fetch multiple columns by using propertiesToFetch
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "<YOUR ENTITY NAME>")
let predicate = NSPredicate(format: "<YOUR PREDICATE>")
fetchRequest.predicate = predicate
fetchRequest.resultType = .dictionaryResultType
// Here is where you can query multiple columns, you can add as much columns as you want and fetch them as an array of dictionaries
fetchRequest.propertiesToFetch = ["column1", "column2", "column3, "column4"]
let sort = NSSortDescriptor(key: "column1", ascending: false)
fetchRequest.sortDescriptors = [sort]