Reputation: 1892
I have an NSArray of 5 NSArrays that each contain NSDictionaries. The dictionaries contain only strings. I'm trying to use NSPredicate to filter out particular dictionaries, however it only seems to work with an exact match. I would like for it to ignore any punctuation such as :
or -
. Here's what I have currently.
NSString *seriesTitle = @" Fullmetal Alchemist Brotherhood - ";
NSPredicate *titlePredicate = [NSPredicate predicateWithFormat:
@"series_title CONTAINS[cd]%@", seriesTitle];
NSArray *filtered = [arraytoEvaluate filteredArrayUsingPredicate:titlePredicate]
Within "arraytoEvaluate" is an NSDictionary containing this key-value pair @"series_title" : @"Fullmetal Alchemist: Brotherhood"
. That's the one I want it to match to. My predicate does not pick this up even though I'm requesting a [cd] search, which I believe ignores punctuation/whitespace, correct?
Using series_title LIKE[cd]%@
gives me this crash:
'NSInvalidArgumentException', reason: 'Can't do regex matching on object
Using BEGINSWITH
instead gives me this:
'NSInvalidArgumentException', reason: 'Can't do a substring operation with something that isn't a string
If I pass in the string exactly, it will pick it up and give me the the Array that contains the dictionary that contains a match, but only if the search term is an exactly match.
Also, it will give me all of them, not an NSArray containing the single NSDictionary that contains a match. I'm not sure what to do about that. I understand that filteredArrayUsingPredicate
is supposed to return an Array, but I will then need to iterate through that Array for the specific NSDictionary that contains a match for the search terms. That's a secondary issue however. Any help would be greatly appreciated.
Upvotes: 0
Views: 1805
Reputation: 53000
You have two problems (a) the match is wrong and (b) you have nested arrays.
(a) [cd]
means ignore case and diacritics, not punctuation and whitespace. A solution here is to use a regular expression and MATCHES[CD]
as the predicate. You need a regular expression which will match the terms you are looking for. A basic re is:
@"fullmetal[^a-z]*alchemist[^a-z]*brotherhood"
where [^a-z]*
matches zero or more (*
) characters from the set [...]
of every character which is not (^
) a letter a-z
.
While this works it probably matches far more than you wish - you should refine the regular expression.
(b) The error you got Can't do regex matching on object...
is because you cannot match a regular expression against an array, and the elements of your array are themselves array. You can address this using a simple loop over the elements, something along the lines of:
NSMutableArray *filtered = [NSMutableArray new]; // allocate an empty mutable array in which to accumulate the matches
for(NSArray *subArray in arraytoEvaluate) // loop over each sub array
[filtered addObjectsFromArray:[subArray filteredArrayUsingPredicate: titlePredicate]]; // and perform the predicate
HTH
Upvotes: 3