zoukankan      html  css  js  c++  java
  • IOS开发之--NSPredicate

    我把常用的NSPredicate使用场景整理了一下
     
    Cocoa提供了一个NSPredicate的类, 指定过滤方式筛选数据。
     
    关于性能我做了个简单的测试,结果如下
     
    数据源500万条数据,计算时间基于5次试验的平均值

    检索数据条数 For循环时间(秒) NSPredicate时间(秒)
    1(位于数据源最后一项) 0.356625 1.487944
    1(位于数据源前1000项) 0.002461 1.516057
    6 1.763434 2.571393
    12 3.466698 3.43019
    24 6.58877 5.465602
    48 12.699893 9.312682
    96 25.36474 17.235685

    从以上测试结果看,苹果对predicate的确做了优化,这种优化随着搜索数据集合的增加逐渐显现出来,

    检索1条数据时,该数据在数据源中的位置对于Nspredicate来说基本没有影响;

    搜索100条数据比for循环节省8秒钟时间,

    但是搜索少量数据如1-10条以内的数据时,for循环还比较占优势  

    下面整理一下常用方法:

    NSPredicate有3种创建方式:格式化字符串/模板/代码方式,下面介绍3种方式

     1.     使用格式化字符串创建

    语法:NSPredicate *predicate = [NSPredicate predicateWithFormat: @"name == 'Herbie'"];
    这里的格式化字符串方式比较丰富,可以用到多种运算符:
     
    ·      比较和逻辑运算符
    ==和=、>、>=和=>、<、<=和=<、!=和<>

    AND、OR、NOT逻辑运算符或者C样式的等效表达式&&、||和!

    示例:
predicate=[NSPredicate predicateWithFormat:@"(engine.horsepower>50) AND (engine.horsepower<200)"];


    字符串中的运算符不区分大小写,你可以随意使用AnD、And或or,
    不等号既适用于数字值又适用于字符串值;
    另外注意表达式的写法支持KVC键路径
     
    ·      数组运算符
    BETWEEN:

    ü  predicate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN {50,200}"];

    ü  NSArray *betweens=[NSArray arrayWithObjects:
    

                      [NSNumber numberWithInt:50],
                   

                      [NSNumber numberWithInt:200],nil];


       predicate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN %@",betweens];

     ü  predicateTemplate=[NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN $POWERS"];


      varDict=[NSDictionary dictionaryWithObjectsAndKeys:betweens,@"POWERS",nil];


      predicate=[predicateTemplate predicateWithSubstitutionVariables:varDict];

    IN:
    	ü predicate=[NSPredicate predicateWithFormat:@"name IN {'Herbie','Snugs','Badger','Flap'}"];
        同理,IN也支持上面描述的between类型的构造方式
     
    ·      字符串运算符
     
        BEGINSWITH

        ENDSWITH

        CONTAINS

     ·      LIKE运算符

          通配符: ? 匹配单个字符 * 匹配任意个字符
    NSPredicate *predicate = [NSPredicate
    				predicateWithFormat:@"lastName like[c] "S*""];

     ·      正则表达式, MATCHES运算符

    NSString *match = @"imagexyz-\d{3}\.png"; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF matches %@", match];

     
    ·     SELF关键字 
     
    格式化字符串中除了使用对象的键路径引用属性,还可以使用
    SELF关键字引用对象本身
    predicate=[NSPredicate predicateWithFormat:@"SELF.name IN {'Herbie','Snugs','Badger','Flap'}"];
     
     ·    [c]、[d]或[cd]修饰符

         为了减少名称匹配规则,可以为这些运算符添加[c]、[d]或[cd]修饰符。其中,c表示“不区分大小写”,d表示“不区分发音符   号”,[cd]表示都不区分。

    例如 "name BEGINSWITH[cd] 'HERB'"

     ·      ALL,ANY关键字

        对象存在关系对象时,有时还会用到ALL,ANY,指明本对象内的xx数组某一个或所有的需要满足xx条件
        [NSPredicate predicateWithFormat:@"ANY entryTags IN %@", selectedTags];
        [NSPredicate predicateWithFormat:@"ALL entryTags IN %@", selectedTags];

     2.     使用Predicate 模板创建

         模板创建是基于字符串创建的,只不过提供了NSPredicate的模板实现方式
    如果使用CoreData,可以使用Xcode的设计工具为Fetchrequest添加Predicate模板,详情可参考https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMOM.html#//apple_ref/doc/uid/TP40002328
    <632B09E1-5DB2-45E5-8A45-73E2B149B108.png>
     
    当然,Predicate模板不仅仅是为CoreData服务的,可以实现自己的模板:
    如上面的between运算符的第三种使用方式就是一种模板的实现
        NSArray *betweens = [NSArray arrayWithObjects:
                                [NSNumber numberWithInt: 50],
                                [NSNumber numberWithInt: 200], nil];
              NSPredicate* predicateTemplate = [NSPredicate predicateWithFormat: @"engine.horsepower BETWEEN $POWERS"];
               varDict = [NSDictionary dictionaryWithObjectsAndKeys: betweens, @"POWERS", nil];
              predicate = [predicateTemplate predicateWithSubstitutionVariables: varDict];

      模板创建NSPredicate主要用于同样的过滤方式,不同的源数据情况下重用NSPredicate的情况使用。

     3.     直接用代码创建

    这种方式是直接使用predicate 和 expression创建NSPredicate,优点是没有使用到字符串解析等大量繁杂的字符串拼接方式,缺点是需要构造大量的expression对象,如下官网给出的实例:
     
    NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"];
     
    NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:1000000]];
     
    NSPredicate *greaterThanPredicate = [NSComparisonPredicate
     
        predicateWithLeftExpression:lhs
     
        rightExpression:greaterThanRhs
     
        modifier:NSDirectPredicateModifier
     
        type:NSGreaterThanOrEqualToPredicateOperatorType
     
        options:0];
     
     
    NSExpression *lessThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:100000000]];
     
    NSPredicate *lessThanPredicate = [NSComparisonPredicate
     
        predicateWithLeftExpression:lhs
     
        rightExpression:lessThanRhs
     
        modifier:NSDirectPredicateModifier
     
        type:NSLessThanPredicateOperatorType
     
        options:0];
     
     
     
    NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
     
        @[greaterThanPredicate, lessThanPredicate]];

     感觉这种方式用起来不太方便,也不太灵活,所以不继续深究了

  • 相关阅读:
    luogu1197 [JSOI2008]星球大战
    luogu2085 最小函数值
    Vijos 1144 小胖守皇宫 【树形DP】
    洛谷 P1941 飞扬的小鸟 【DP+众多特判】
    codevs 1516 平均分数 【数学推理+求逆序对】
    tyvj 1936 太空战队 【强连通分量】
    USACO 2.4 Overfencing 【种子染色法+递推】
    code[vs] 2488 绿豆蛙的归宿【反向拓扑+DP】
    USACO 2.3 Zero Sum 【搜索+字符串处理+模拟计算】
    USACO 2.3 Cow Pedigrees 【DP+前缀和优化】
  • 原文地址:https://www.cnblogs.com/v-jing/p/3169081.html
Copyright © 2011-2022 走看看