NSPredicate 未按需要过滤

Posted

技术标签:

【中文标题】NSPredicate 未按需要过滤【英文标题】:NSPredicate not filtering as desired 【发布时间】:2015-07-14 19:59:17 【问题描述】:

考虑以下数组:

NSArray *dataValues = @[@"Foo[0]", @"Foo[1].bar"];

以及以下正则表达式模式、谓词和预期输出:

NSString *pattern = @"Foo[0]";
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF BEGINSWITH[cd] %@", pattern];
NSArray *results = [dataValues filteredArrayUsingPredicate: predicate];
NSLog(@"matches = %ld", (long)results.count);

这会按预期在控制台中打印1。如果我们将模式更改为:

NSString *pattern = @"Foo\\[[0-9]\\]";

我希望这会在控制台中打印2,但它会打印0。我已经对外部方括号进行了双重转义,以允许对其进行解析,并希望找到括号内具有数字 0 到 9 的字符串以匹配此表达式。

我已经根据以下网站检查了正则表达式,它确实可以正常工作:

http://regexr.com/3bcut

我在针对 ios 8.4 iPhone 6 Plus 模拟器运行的 Xcode(6.4、6E35b)中没有警告/错误,但为什么我的正则表达式没有按预期过滤?

【问题讨论】:

【参考方案1】:

你可以根据自己的需要试试这个:

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

你可以更基本一点并使用

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

【讨论】:

您好,感谢您的回答。我可以理解使用字符串前缀检查(等)的替代方法,但方括号内的整数需要是动态范围,例如 0-9、10-19 等,因为代码位于 for 循环内 - 但是令我沮丧的是为什么我的正则表达式不起作用!也许是一个错误?【参考方案2】:

在与 Apple 提出 TSI 之后(好吧,谁会使用这些东西?)他们说我只需要使用 MATCHES 而不是 BEGINSWITH,后者仅用于字符串匹配 - 而我正在尝试匹配一个正则表达式。

因此,我的谓词应该是:

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES[cd] %@", pattern];

【讨论】:

以上是关于NSPredicate 未按需要过滤的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 未按预期给出结果

NSpredicate 上的正则表达式未按预期工作

Swift CoreData NSPredicate

NSPredicate 从 PHFetchResults 中排除慢动作视频

使用 NSPredicate 过滤对象和键(需要拆分)

使用 NSPredicate 过滤 EKEvent