文章目录

  • NSPredicate 简述
  • 使用示例
  • 一、过滤数值
  • 1、判断数值相等、大小等
  • 2、判断数值范围 Between
  • 二、过滤字符串
  • 1、BEGINSWITH:是否以指定字符串开头
  • 2、ENDSWITH:是否以指定字符串结尾
  • 3、CONTAINS:是否包含指定字符串
  • 4、LIKE & ?:是否匹配指定字符串模板
  • 4.1 `?` 代表一个字符
  • 4.2* 代表任意多个字符
  • 5、MATCHES:是否匹配指定的正则表达式
  • 6、字符串比较都是区分大小写和重音符号的。
  • 7、IN 运算
  • AND(或&&)
  • 三、过滤数组、Set
  • 0、过滤方法
  • 过滤 NSArray:`filteredArrayUsingPredicate:`
  • NSMutableArray:`filterUsingPredicate:`
  • NSSet `filteredSetUsingPredicate:`
  • NSMutableSet `filterUsingPredicate:`
  • 1、数值数组筛选
  • 2、字符串数组的筛选
  • 3、取两个数组的交集
  • 4、过滤模型数组
  • predicateWithSubstitutionVariables
  • 参考资料



NSPredicate 简述

NSPredicate类是一种过滤器,用来定义 逻辑条件约束的获取 或 内存中的。

在别写 NSPredicate 语句的时候,可以使用

  • 比较运算符: 大于等于 >=,=>, 小于等于<=,=<,不等于!=、<>, 相等 =;
  • 逻辑运算符(与或非)AND、&&;OR、||;NOT、 !;
  • 字符串比较运算符:BEGINSWITH、ENDSWITH、CONTAINS、LIKE
  • 集合运算符:ANY、SOME、ALL、NONE、IN
  • 直接量:FALSE、NO;TRUE、YES;NULL、NIL;SELF、"string"或’string’;数组,如:{‘one’, ‘two’, ‘three’}(和c中的写法相同);数值、十六进制数:0x开;八进制:0o开头;二进制:0b开头的数字。
  • 保留字:AND、OR、IN、NOT、ALL、ANY、SOME、NONE、LIKE、CASEINSENSITIVE、CI、MATCHES、CONTAINS、BEGINSWITH、ENDSWITH、BETWEEN、NULL、NIL、SELF、TRUE、YES、FALSE、NO、FIRST、LAST、SIZE、ANYKEY、SUBQUERY、CAST、TRUEPREDICATE、FALSEPREDICATE

使用示例

一、过滤数值

是否复合某个条件,返回BOOL,使用方法如:
下面例子,都是用下面数值做测试:

NSNumber *num0 = @123;
    NSNumber *num1 = @1234;
    NSString *str0 = @"123";

1、判断数值相等、大小等

  • =、:判断两个表达式是否相等,在谓词中=和是相同的意思都是判断,而没有赋值这一说;
  • 字符串不能使用 = 判断;
NSNumber *num0 = @123;
    NSNumber *num1 = @1234;
    NSString *str0 = @"123";
    
    NSPredicate *pre0 = [NSPredicate predicateWithFormat:@"SELF = 123"];
    NSLog(@"%d",[pre0 evaluateWithObject:num0]);//1
    NSLog(@"%d",[pre0 evaluateWithObject:num1]);//0
    NSLog(@"%d",[pre0 evaluateWithObject:str0]);//0
    
    NSPredicate *pre1 = [NSPredicate predicateWithFormat:@"SELF > 1000"];
    NSLog(@"%d",[pre1 evaluateWithObject:num0]);//1
    NSLog(@"%d",[pre1 evaluateWithObject:num1]);//0

2、判断数值范围 Between

  • 表达式 BETWEEN {下限,上限}的格式,要求该表达式必须大于或等于下限,并小于或等于上限
NSPredicate *pre2 = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
    NSLog(@"%d",[pre2 evaluateWithObject:num0]);//1
    NSLog(@"%d",[pre2 evaluateWithObject:num1]);//0

二、过滤字符串

1、BEGINSWITH:是否以指定字符串开头

如:判断字符串是否以a开头:BEGINSWITH ‘a’)

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH 'a'"];
    
    NSLog(@"%d",[pre evaluateWithObject:@"ab"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"abc"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"ba"]);//0

2、ENDSWITH:是否以指定字符串结尾

如:判断字符串是否以ba结尾:ENDSWITH ‘ba’)

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF ENDSWITH 'ba'"];
    
    NSLog(@"%d",[pre evaluateWithObject:@"ab"]);//0
    NSLog(@"%d",[pre evaluateWithObject:@"abc"]);//0
    NSLog(@"%d",[pre evaluateWithObject:@"ba"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"cba"]);//1

3、CONTAINS:是否包含指定字符串

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF CONTAINS 'jo'"];
    
    NSLog(@"%d",[pre evaluateWithObject:@"John"]);//0
    NSLog(@"%d",[pre evaluateWithObject:@"john"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"Milly"]);//0

4、LIKE & ?:是否匹配指定字符串模板

其之后可以跟?代表一个字符和*代表任意多个字符两个通配符。

4.1 ? 代表一个字符

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF LIKE '?ng'"];
    NSLog(@"%d",[pre evaluateWithObject:@"png"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"jpng"]);//0

4.2* 代表任意多个字符

样式类似 前缀为 ang,后面跟随其他字符:

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF LIKE 'ang*'"];
    
    NSLog(@"%d",[pre evaluateWithObject:@"ango"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"angel"]);//1
    NSLog(@"%d",[pre evaluateWithObject:@"jiang"]);//0

上面条件,angle和lenang都符合;
你也可以把 * 放到 ang 前面。


5、MATCHES:是否匹配指定的正则表达式

虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。

- (void)checkPhoneNumber
{
    NSString *regex = @"^[1][3-8]\\d{9}$";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    NSLog(@"%d", [pred evaluateWithObject:@"15818663297"]);//1
    NSLog(@"%d", [pred evaluateWithObject:@"303178203"]);//0
}

6、字符串比较都是区分大小写和重音符号的。

如:café和cafe是不一样的,Cafe和cafe也是不一样的。判断时可以加上下面符号进行区分:

[c] 忽略大小写;
[d] 忽略重音符号;比如:name LIKE[cd] ‘cafe’,那么不论name是cafe、Cafe还是café上面的表达式都会返回YES。
[cd]既不区分大小写,也不区分发音符号。

NSArray *stringArray = @[@"John",@"john",@"Jolly",@"Milly"];
    NSString *targetString = @"jo";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@",targetString];
    NSLog(@"%@",[stringArray filteredArrayUsingPredicate:pred]);// John,john,Jolly

7、IN 运算

对于 NSString类型,判断title属性是否是字符串@"angle"和@"addss"中的一个:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF IN {'angle', 'addss'}"];
    NSLog(@"%d", [pred evaluateWithObject:@"angle"]);//1
    NSLog(@"%d", [pred evaluateWithObject:@"blue"]);//0

对于 NSNumber类型,判断testID属性是否是NSNumber对象中的@1和@13中的一个:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF IN {1, 13}"];
    
    NSLog(@"%d", [pred evaluateWithObject:@(13)]);//1
    NSLog(@"%d", [pred evaluateWithObject:@(5)]);//0

AND(或&&)

NSPredicate *pred = [NSPredicate predicateWithFormat:@“testID >= %@ AND testID <=%@”, @1ll, @13ll];


三、过滤数组、Set

0、过滤方法

过滤 NSArray:filteredArrayUsingPredicate:

使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的 新集合

NSMutableArray:filterUsingPredicate:

使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素

NSSet filteredSetUsingPredicate:

NSMutableSet filterUsingPredicate:

通过上面的描述可以看出,使用谓词过滤不可变集合和可变集合的区别是:过滤不可变集合时,会返回符合条件的集合元素组成的新集合;过滤可变集合时,没有返回值,会直接剔除不符合条件的集合元素


1、数值数组筛选

数值数组,筛选数值在某个范围内

NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
    NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
    NSLog(@"filterArray:%@", filterArray);//3,4

2、字符串数组的筛选

常用的一般根据包含内容、字符串长度进行筛选
其他功能可参考上面对字符串进行判断的方法

- (void)testPre1{
    NSArray *testArray = @[@"JOLLY",@"billy", @"John", @"Joe", @"Tiffany", @"Mary", @"David"];
    //筛选字符长度大于4的元素
    NSPredicate *pre0 = [NSPredicate predicateWithFormat:@"SELF.length > 4"];
    NSArray *filterArray0 = [testArray filteredArrayUsingPredicate:pre0];
    
    NSLog(@"filterArray0:%@", filterArray0);//billy,Tiffany,David
    
    //取出包含‘Jo’的元素
    NSPredicate *pre1 = [NSPredicate predicateWithFormat:@"SELF CONTAINS 'Jo'"];
    NSArray *filterArray1 = [testArray filteredArrayUsingPredicate:pre1];
    NSLog(@"filterArray1:%@", filterArray1);//John,Joe
    
    NSString *keyword = @"Jo";
    NSPredicate *pre2 = [NSPredicate predicateWithFormat:@"SELF.lowercaseString CONTAINS '%@'",keyword.lowercaseString];
    
    NSArray *filterArray2 = [testArray filteredArrayUsingPredicate:pre2];
    NSLog(@"filterArray2:%@", filterArray2);//JOLLY,John,Joe
}

3、取两个数组的交集

使用 集合运算符中的 IN 运算符

NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
    NSArray *subArray = @[@"ab", @"abc",@"ab1"];
    
    NSPredicate *pre0 = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", subArray];//不包含在subArray的元素
    NSLog(@"0-%@", [array filteredArrayUsingPredicate:pre0]);//a,abcd
    
    
    NSPredicate *pre1 = [NSPredicate predicateWithFormat:@"SELF IN %@", subArray];//包含在subArray的元素
    NSLog(@"1-%@", [array filteredArrayUsingPredicate:pre1]);//ab,abc

4、过滤模型数组

这里创建一个模型 PersonModel 方便解释下面使用,PersonModel 包含属性:

@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *sex;
@property (nonatomic,assign) NSInteger age;
-(instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age;

创建测试数据:

PersonModel *model0 = [[PersonModel alloc]initWithName:@"joe" sex:@"female" age:18];
    PersonModel *model1 = [[PersonModel alloc]initWithName:@"jim" sex:@"female" age:20];
    PersonModel *model2 = [[PersonModel alloc]initWithName:@"jone" sex:@"female" age:23];
    PersonModel *model3 = [[PersonModel alloc]initWithName:@"milly" sex:@"female" age:25];
    PersonModel *model4 = [[PersonModel alloc]initWithName:@"Elaine" sex:@"female" age:28];
    
    NSArray *array = @[model0,model1,model2,model3,model4];

筛选名字包含 jo 的模型, 下面四种方式搜索结果相同:

NSPredicate *pred0 = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", @"name", @"jo"];
    NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"name CONTAINS %@", @"jo"];
    NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"SELF.name CONTAINS %@", @"jo"];
    NSPredicate *predTemp3 = [NSPredicate predicateWithFormat:@"%K CONTAINS $VALUE", @"name"];
    NSPredicate* pred3 = [predTemp3 predicateWithSubstitutionVariables:@{@"VALUE" : @"jo"}];
    
    NSLog(@"%@", [array filteredArrayUsingPredicate:pred0]);
    NSLog(@"%@", [array filteredArrayUsingPredicate:pred1]);
    NSLog(@"%@", [array filteredArrayUsingPredicate:pred2]);
    NSLog(@"%@", [array filteredArrayUsingPredicate:pred3]);

其中

  • 属性作为key,可以用 %K 表示。
  • 使用 $ 修饰的字符,可以作为参数,在 predicateWithSubstitutionVariables 中使用字典的形式赋值;在其他时候赋值,也方便产生多个条件类似的过滤器。Value 字符也可以替换为其他字符,只要前后统一即可,最好不要用关键字。
    下面示例同样使用到这个方法,方便你的理解:

predicateWithSubstitutionVariables

// 创建谓词,属性名改为age,要求这个age包含$VALUE字符串
    NSPredicate *predTemp4 = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
    // 指定$VALUE的值为 20
    NSPredicate *pred4 = [predTemp4 predicateWithSubstitutionVariables:@{@"VALUE" : @20}];
    NSLog(@"%@", [array filteredArrayUsingPredicate:pred4]);//筛选到年级大于20的模型