NSPredicate使用小总结

为什么要使用NSPredicate?

在做应用实现的过程中,经常会遇到一些筛选符合条件数据的需求,对于普通人来说,设计出一个筛选速度很快的算法并不是一件容易的事.所以iOS内部将这些实现进行了封装,便于友好地支持开发者的使用,降低使用的难度,加快开发的进程.

NSPredicate的使用场景

NSPredicate的使用多数是通过使用不同的谓词来实现,通过常用的谓词来介绍在开发场景中的使用.例如:

Match

NSPredicate的第一个强大的功能就是直接用于类型的匹配,使用起来跟正则表达式类似,用于匹配到符合条件的元素

  • 匹配全是中文的字符串
    NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!", @"I like china"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^[\\u4e00-\\u9fa5]+$"];
    for (NSString * ele in array) {
        NSLog(@"[%@]中%@都是中文字符", ele, [predicate evaluateWithObject:ele] ? @"全部" : @"非全部");
    }
  • 匹配字符串中是否包含中文
   NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!"];
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @".*[\\u4e00-\\u9fa5]+.*"];
   for (NSString * ele in array) {
       NSLog(@"[%@]中%@中文字符", ele, [predicate evaluateWithObject:ele] ? @"包含" : @"不包含");
   }

Contains

contains主要用于筛选匹配包含指定字串的字符串。例如:

  • 匹配字符串中是否包含指定字串
    NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!", @"I like china"];
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@", @"China"];
   for (NSString * ele in array) {
       NSLog(@"[%@]中%@[China]", ele, [predicate evaluateWithObject:ele] ? @"包含" : @"不包含");
   }
  • 匹配字符串中是否包含指定的子串(忽略大小写)
    如果需要忽略大小写可以使用[c]来做筛选选项.多数情况下会与[d]一起使用,该筛选项表示忽略重音符号.
    NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!", @"I like china"];
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", @"China"];
   for (NSString * ele in array) {
       NSLog(@"[%@]中%@[China]", ele, [predicate evaluateWithObject:ele] ? @"包含" : @"不包含");
   }

BeginsWith && EndsWith

主要用于筛选以指定子串开头/结尾的字符串.例如:

  • 筛选以China开头的字符串(不区分大小写)
    NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!", @"I like china"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"China"];
    for (NSString * ele in array) {
        NSLog(@"[%@]%@以%@开头", ele, [predicate evaluateWithObject:ele] ? @"是" : @"不是", @"China");
    }
  • 筛选以China结尾的字符串(不区分大小写)
    NSArray <NSString *> *array = @[@"ABC", @"我是一个老男孩", @"China,加油!", @"I like china"];
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH[c] %@", @"China"];
   for (NSString * ele in array) {
       NSLog(@"[%@]%@以%@结尾", ele, [predicate evaluateWithObject:ele] ? @"是" : @"不是", @"China");
   }

Like

主要用于筛选具备某一类相似特征的字符串,通常使用*作为通配符.例如:

  • 筛选以.png结尾的资源名称
    NSArray <NSString *> *array = @[@"loading_001.png", @"loading_002.png", @"loading_003.png",@"我是一个老男孩", @"China,加油!", @"I like china"];
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF LIKE %@", @"loading_*.png"];
   for (NSString * ele in array) {
       NSLog(@"[%@]%@形如[loading_*.png]条件", ele, [predicate evaluateWithObject:ele] ? @"符合" : @"不符合");
   }

In

主要用于在集合中筛选出共同部分,例如:

  • 在数组array1中帅选出与数组array2相同的元素:
    NSArray <NSString *> *array1 = @[@"one", @"two", @"three", @"four"];
   NSArray <NSString *> *array2 = @[@"three", @"four", @"five"];
   
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", array2];
   NSArray<NSString *> *commonElements = [array1 filteredArrayUsingPredicate:predicate];
   NSLog(@"commonElements == %@", commonElements);
  • 筛选出set1中与set2中相同的元素:
    NSSet<NSString *> *set1 = [NSSet setWithObjects:@"one", @"two", @"three", @"four", nil];
   NSSet<NSString *> *set2 = [NSSet setWithObjects:@"three", @"four", @"five", nil];
   
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", set2];
   NSSet<NSString *> *commonElements = [set1 filteredSetUsingPredicate:predicate];
   NSLog(@"commonElements == %@", commonElements);

Not

主要用于相反选择,用于筛选出不符合指定条件的元素.例如:

  • 筛选出array1与array2不相同的元素:
    NSSet<NSString *> *set1 = [NSSet setWithObjects:@"one", @"two", @"three", @"four", nil];
   NSSet<NSString *> *set2 = [NSSet setWithObjects:@"three", @"four", @"five", nil];
   
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", set2];
   NSSet<NSString *> *commonElements = [set1 filteredSetUsingPredicate:predicate];
   NSLog(@"commonElements == %@", commonElements);
  • 筛选出数组中不符合like规则的元素:
    NSArray <NSString *> *array = @[@"loading_001.png", @"loading_002.png", @"loading_003.png",@"我是一个老男孩", @"China,加油!", @"I like china"];
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF LIKE %@)", @"loading_*.png"];
  for (NSString * ele in array) {
      NSLog(@"[%@]%@形如[loading_*.png]条件", ele, [predicate evaluateWithObject:ele] ? @"不符合" : @"符合");
  }

逻辑运算符号

还可以使用诸如==, >, <, >=, <=, 以及AND, OR等逻辑运算符号进行条件筛选.
为了方便说明,定一个Student类:

@interface Student : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) CGFloat score;
- (instancetype)initWithName: (NSString *)name score: (CGFloat)score;
@end

@implementation Student
- (instancetype)initWithName: (NSString *)name score: (CGFloat)score {
    self = [super init];
    if (self) {
        self.name = name;
        self.score = score;
    }
    return self;
}
@end

并创建students数组

    NSArray<Student *> *students = @[
        [[Student alloc] initWithName:@"Frank" score:77],
        [[Student alloc] initWithName:@"Dong" score:99],
        [[Student alloc] initWithName:@"Ping" score:88],
        [[Student alloc] initWithName:@"Chao" score:80],
    ];
    
  • 筛选出name="Dong"的同学:
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name == %@ ", @"Dong"];
   NSArray<Student *> *result =  [students filteredArrayUsingPredicate:predicate];
   NSLog(@"result == %@, name == %@", result, result.firstObject.name);

**使用属性进行筛选时,可以省略SELF,直接使用属性名进行筛选,简化书写。**例如筛选成绩小于60,大于90的同学时可以直接使用:
"score < 60 OR score >90 "

  • 筛选出成绩大于80且小于90的同学:
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"score >= 80 and score <= 90"];
   NSArray<Student *> *result =  [students filteredArrayUsingPredicate:predicate];
   for (Student *stu in result) {
       NSLog(@"name == %@, score == %lf", stu.name, stu.score);
   }

Attention:
需要注意的一点是,当属性名作为参数传入匹配范型的时候,不能使用%@进行参数格式限定,而应该使用%K进行格式限定。因为在默认的情况下,使用%@时,系统会给参数添加引号,例如

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@ ", @"Dong"];

编译之后会变成形如:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Dong' "];

而不是:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"'name' == 'Dong' "];

所以当参数名需要使用参数进行传递时,需要使用

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@ ", @"name", @"Dong"];

而不是:

  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ == %@ ", @"name", @"Dong"];
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值