美文网首页iOS基础
NSPredicate相关笔记

NSPredicate相关笔记

作者: 阿洋12138 | 来源:发表于2018-04-25 20:43 被阅读10次

    关于 NSPredicate

    简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取。

    常用的表达式

    (1)比较运算符>,<,==,>=,<=,!=,可用于数值及字符串

    =、==:判断两个表达式是否相等,在谓词中=和==是相同的意思都是判断,而不是赋值
    例:

    NSNumber *number = @727;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 728"];
    if ([predicate evaluateWithObject:number]) {
        NSLog(@"testString:%@", number);
    }
    

    (2)范围运算符:IN、BETWEEN

    例:

    @"number BETWEEN {1,5}"
    @"address IN {'shanghai','beijing'}"
    

    (3)字符串本身:SELF

    例:

    @"SELF == ‘APPLE’"
    

    (4)字符串相关:BEGINSWITH、ENDSWITH、CONTAINS、LIKE

    BEGINSWITH :检查某个字符串是否以指定的字符串开头

    ENDSWITH :检查某个字符串是否以指定的字符串结尾

    CONTAINS :检查某个字符串是否包含指定的字符串

    LIKE :检查某个字符串是否匹配指定的字符串模板。其之后可以跟?代表一个字符和*代表一个或者多个或者是空。比如"name LIKE '*ac*'",这表示name的值中包含ac则返回YES;"name LIKE '?ac*'",表示name的第2、3个字符为ac时返回YES。

    例:

    @"name CONTAIN[cd]   'ang'"    //包含某个字符串
    @"name BEGINSWITH[c] 'sh'"     //以某个字符串开头
    @"name ENDSWITH[d]   'ang'"    //以某个字符串结束
    NSString *string = @"abcd BEGINSWITH 'a'";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:string];
    

    注:

    注: 字符串比较都是区分大小写和重音符号的。
    如:café和cafe是不一样的,Cafe和cafe也是不一样的。
    如果希望字符串比较运算不区分大小写和重音符号,
    请在这些运算符后使用[c],[d]选项。
    其中
    [c]不区分大小写
    [d]不区分发音符号即没有重音符号
    [cd]既不区分大小写,也不区分发音符号。
    其写在字符串比较运算符之后,比如:"name LIKE[cd] 'cafe'",
    那么不论`name`是cafe、Cafe还是café上面的表达式都会返回YES。
    

    (5)正则表达式:MATCHES

    MATCHES:检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率并不高,但其功能是最强大的,也是我们最常用的。[c],[d],[cd]同样适用
    例:

      NSString *regex = @"^A.+e$";   //以A开头,e结尾
      NSString *regex = @"[A-Za-z]+";//判断字符串首字母是否为字母:
      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    
    

    正则表达式请参考:iOS正则表达式的简单使用

    (6)集合运算符

    ANY、SOME :集合中任意一个元素满足条件,就返回YES。

    ALL :集合中所有元素都满足条件,才返回YES。

    NONE :集合中没有任何元素满足条件就返回YES。

    IN:等价于SQL语句中的IN运算符,只有当左边表达式或值出现在右边的集合中才会返回YES。我们通过一个例子来看一下

    //相同的元素去除
    NSArray *filterArray = @[@"ab", @"abc",@"uy"];
    NSArray *array       = @[@"a", @"ab", @"abc", @"abcd"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
    NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
    

    (7)直接量

    FALSE、NO:代表逻辑假

    TRUE、YES:代表逻辑真

    NULL、NIL:代表空值

    SELF :代表正在被判断的对象自身

    "string"或'string':代表字符串

    数组:和c中的写法相同,如:{'one', 'two', 'three'}

    数值:包括整数、小数和科学计数法表示的形式

    十六进制数:0x开头的数字

    八进制:0o开头的数字

    二进制:0b开头的数字

    (8)保留字 (不区分大小写)

    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

    提示

    实际上在实际开发中OC对几个集合类提供了NSPredicate的过滤方法
    • NSArray提供了如下方法使用谓词来过滤集合
      - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的新集合

    • NSMutableArray提供了如下方法使用谓词来过滤集合
      - (void)filterUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素

    • NSSet提供了如下方法使用谓词来过滤集合
      - (NSSet *)filteredSetUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSArray中的方法

    • NSMutableSet提供了如下方法使用谓词来过滤集合
      - (void)filterUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSMutableArray中的方法。

    1.首先假定有一个对象Person 其中Person有个属性叫做name和age
    现在创建Person对象
    Person *person = [Person alloc]init];
    
    person.name = @"nie";
    
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"name LIKE 'n*'"];
    
    NSLog(@"%d", [pred evaluateWithObject:person]);
    
    >这里的输出是1.
    
    NSPredicate的实例对象调用的evaluateWithObject方法,
    是基于OC对象的,所以说 @"name LIKE 'n*'" 这里的name是对象person中的一个属性,
    这里判断的是person对象的name属性是不是以n开头的。
    在实际开发中很多情况下做数据的处理是基于我们自定义的对象,
    多使用NSPredicate可以有助于实际开发中简化代码的逻辑,
    减少使用for循环,if语句这些啰嗦的代码
    
    如果我们想在谓词表达式中使用变量,那么我们需要了解下列两种占位符:
    
    `%K`:用于动态传入属性名
    
    `%@`:用于动态设置属性值
    
    其实相当于变量名与变量值,除此之外,还可以在谓词表达式中使用动态改变的属性值,就像环境变量一样
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS $VALUE"];
    上述表达式中,`$VALUE`是一个可以动态变化的值,它其实最后是在字典中的一个key,所以可以根据你的需要写不同的值,但是必须有$开头,随着程序改变`$VALUE`这个谓词表达式的比较条件就可以动态改变。
    
    下面我们通过一个例子来看看这三个重要的占位符应该如何使用
    
    NSArray *array = @[person0,person1,person2];
    
    // 定义一个property来存放属性名,定义一个value来存放值
    NSString *property = @"name";
    NSString *value = @"nie";
    
    // 该谓词的作用是如果元素中property属性含有值value时就取出放入新的数组内,这里是name包含nie
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
    NSArray *newArray = [array filteredArrayUsingPredicate:pred];
    NSLog(@"newArray:%@", newArray);
    
    // 创建谓词,属性名改为age,要求这个age包含$VALUE字符串
    NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
    // 指定$VALUE的值为 25
    NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
    NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
    NSLog(@"newArray1:%@", newArray1);
    
    // 修改 $VALUE的值为32
    NSPredicate *pred2 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @32}];
    NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];
    NSLog(@"newArray2:%@", newArray2);
    

    代码应用

    (1)对NSArray进行过滤

    NSArray *array = [[NSArray alloc]initWithObjects:@"beijing",@"shanghai",@"guangzou",@"wuhan", nil];   
    NSString *string = @"ang";   
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@",string];   
    NSLog(@"%@",[array filteredArrayUsingPredicate:pred]);
    

    (2)判断字符串首字母是否为字母:

    NSString *regex = @"[A-Za-z]+";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    if ([predicate evaluateWithObject:@"rrrkmr"]) {
        NSLog(@"1");
    }else{
        NSLog(@"2");
    }
    

    (3)检查某个字符串是否以指定的字符串开头

    NSString *string = @"abcdefg";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@" %@ BEGINSWITH 'a'",string];
    if ([predicate evaluateWithObject:string]) {
        NSLog(@"string:%@", string);
    }
    

    (4)过滤数组中重复的元素 模型数组通用

    /**
     根据modelArray中的属性 去除重复的元素
     目前我的测试中 NSString 和 int类型是没有问题的,过滤正常.
     感慨一下,系统的数组提供的过滤器,排序方式真的很强大
    
     @param object 模型数组
     @param keypath 模型数组元素中的一个属性
     @return 过滤之后的新数组
     */
     +(NSArray *)ht_removeRepeatRowsForArray:(NSArray *)object
                                 WithKeypath:(NSString *)keypath
     {
         NSMutableSet *seenObjects = [NSMutableSet set];
         NSPredicate * predicate = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
             id property = [obj valueForKeyPath:keypath];//元素属性
             BOOL seen = [seenObjects containsObject:property];
             if (!seen) {
                 [seenObjects addObject:property];
             }
             return !seen;
         }];
         NSMutableArray *categoryArray = [NSMutableArray arrayWithArray:[object filteredArrayUsingPredicate:predicate]];
         return categoryArray;
     }
    

    相关文章

      网友评论

        本文标题:NSPredicate相关笔记

        本文链接:https://www.haomeiwen.com/subject/fhfulftx.html