NSPredicate does not filter at will
Consider the following array:
NSArray *dataValues = @[@"Foo[0]", @"Foo[1].bar"];
And the following regex pattern, predicate and expected output:
NSString *pattern = @"Foo[0]";
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF BEGINSWITH[cd] %@", pattern];
NSArray *results = [dataValues filteredArrayUsingPredicate: predicate];
NSLog(@"matches = %ld", (long)results.count);
Will print 1
to console as expected. If we change the template to:
NSString *pattern = @"Foo\\[[0-9]\\]";
I expect this to print 2
to the console, but it will print 0
. I escape the outer square brackets twice so that they can be parsed and expect to find strings that have numbers between 0 and 9 in parentheses to match this expression.
I have tested the regex on the following site, which works correctly:
I have no warnings / errors in Xcode (6.4, 6E35b) working against the iOS 8.4 iPhone 6 Plus simulator, but why is my regex not filtering as expected?
source to share
After raising TSI with Apple (well, who's using these things anyway?), They said that I just need to use MATCHES
instead BEGINSWITH
, which is only used for string matching, whereas I am trying to match a regex.
So my predicate should read:
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES[cd] %@", pattern];
source to share
You can try this depending on your needs:
NSArray *dataValues = @[@"Foo[0]", @"Foo[1].bar"];
NSString *pattern = @"Foo[*]*";
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF LIKE %@", pattern];
NSArray *results = [dataValues filteredArrayUsingPredicate: predicate];
NSLog(@"matches = %ld", (long)results.count);
You can go a little more thoroughly and use
NSMutableArray *results = [NSMutableArray array];
for (NSString *str in dataValues) {
if ([str rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) {
if ([str hasPrefix:@"Foo["]) {
[results addObject:str];
}
}
}
NSLog(@"matches = %ld", (long)results.count);
source to share