【问题标题】:Multiple conditions in NSPredicateNSPredicate 中的多个条件
【发布时间】:2012-04-25 18:58:45
【问题描述】:

NSPredicate如何使用多个条件?

我正在使用它,但在返回的数组中没有得到任何东西。

NSPredicate *placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@ AND category CONTAINS[cd] %@ AND ((dates >= %@) AND (dates <= %@)) AND ((amount >= %f) AND (amount <= %f))",placeTextField.text,selectedCategory,selectedFromDate,selectedToDate,[amountFromTextField.text floatValue],[amountToTextField.text floatValue]];

NSArray *placePredicateArray = [dataArray filteredArrayUsingPredicate:placePredicate];

NSLog(@"placePredicateArray %@", placePredicateArray);

金额和类别有时可以为空。我应该如何构造NSPredicate

【问题讨论】:

    标签: objective-c ios cocoa-touch ipad nspredicate


    【解决方案1】:

    您可以使用其他 NSPredicate 对象和 NSCompoundPredicate 类来构建您的 placesPredicate

    类似:

    NSPredicate *p1 = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@", placeTextField.text];
    NSPredicate *p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory];
    NSPredicate *p3 = [NSPredicate predicateWithFormat:@"(dates >= %@) AND (dates <= %@)", selectedFromDate,selectedToDate];
    NSPredicate *p4 = [NSPredicate predicateWithFormat:@"(amount >= %f) AND (amount <= %f)", [amountFromTextField.text floatValue],[amountToTextField.text floatValue]]; 
    
    NSPredicate *placesPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[p1, p2, p3, p4]];
    

    现在,如果您缺少类别,例如,您可以使用虚拟的 YES 谓词来替换它:

    NSPredicate *p2;
    if (selectedCategory) {
        p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory];
    } else {
        p2 = [NSPredicate predicateWithBool:YES]
    }
    

    【讨论】:

    • 谢谢。这对我帮助很大。谢谢
    • 但是如何从 NSPredicate 获取数组?
    • 如果您需要获取用于创建复合词的谓词数组,请使用NSCompoundPredicatesubpredicates 属性。您还应该好好看看@DRVic 的回答——他会随着他的进展动态地创建谓词数组——这会更有效率,因为他不需要包含任何YES 谓词,但这意味着你不需要t 很容易知道哪个谓词在子谓词数组中的哪个索引处。
    • PS 显然,只有NSCompoundPredicate 的实例才会有一个子谓词数组属性。把普通的NSPredicate 变成数组是没有意义的!
    【解决方案2】:

    我倾向于零碎地处理这件事。也就是说,

    placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@",placeTextField.text];
    NSMutableArray *compoundPredicateArray = [ NSMutableArray arrayWithObject: placePredicate ]; 
    
    if( selectedCategory != nil ) // or however you need to test for an empty category
        {
        categoryPredicate = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@",selectedCategory];
        [ compoundPredicateArray addObject: categoryPredicate ];
        }
    
    // and similarly for the other elements.  
    

    请注意,当我知道没有谓词时,我什至不费心将类别(或其他任何东西)的谓词放入数组中。

    // Then
        NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
                                      compoundPredicateArray ];
    

    如果我打算做很多事情,我不会使用 format 方法,而是保留构建块,只是在使用之间更改任何更改。

    【讨论】:

    • 对此评论 +1 // or however you need to test for an empty category 真的帮助了我.. 谢谢! :)
    【解决方案3】:
    Suppose a class Person with attributes "name", "age", "income"
    
    "personArray" is array of class Person
    
    NSPredicate *mypredicate = [NSPredicate predicateWithBlock:^BOOL(personObj Person, NSDictionary *bindings) {
         NSNumber *age = personObj.age;
         String *name = personObj.name;
         NSNumber *income = personObj.income
         BOOL result = (age > 20 && name == "Stack" && income >40000);
         return result;
    }];
    
    NSArray *filteredArray = [personArray filteredArrayUsingPredicate: mypredicate];
    

    更多内容你可以阅读这篇文章Array Filter Using Blocks

    在斯威夫特中

    let filterArray = personArray.filter
                { person in
               let age = personObj.age;
               let name = personObj.name;
               let income = personObj.income
               BOOL result = (age > 20 && name == "Stack" && income >40000);
              return result;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      • 2015-01-06
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多