复合谓词 NSPredicate

Posted

技术标签:

【中文标题】复合谓词 NSPredicate【英文标题】:CompoundPredicate NSPredicate 【发布时间】:2016-04-22 11:10:15 【问题描述】:

例如,我有三个 NSPredicate。

NSPredicate *pred1 = [NSpredicate ...];
NSPredicate *pred2 = [NSpredicate ...];
NSPredicate *pred3 = [NSpredicate ...];

我从服务器字符串中获得了我需要组合谓词的方式。

举例

(1 OR 2 OR 3)
(1 OR 3) AND 2
3 OR (1 AND 2)

如何在正确的条件下结合我的三个谓词并给出括号?

谢谢

【问题讨论】:

【参考方案1】:

你总是可以像这样创建嵌套的NSCompoundPredicate

NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[firstPredicate, secondPredicate]];
NSPredicate *andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[thirdPredicate, fourthPredicate]];
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[orPredicate, andPredicate]];

【讨论】:

每次我可以有不同的字符串。而且我不能有三个,例如十个(1 OR 2 AND (3 OR 4) AND (5 OR 6) AND 7 AND 8 AND 10) 你总是可以组合那些不在大括号内的,对吧?像这样:(2 AND 7 AND 8 AND 10 AND (3 OR 4) AND (5 or 6) OR 1)。现在你可以像这样进行谓词:NSPredicate *andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[2,7,8,10]]; 等等......【参考方案2】:

一种方法是从您的谓词中创建一个“真值表输入”,根据字符串创建一个组合谓词,并使用真值表数据对其进行评估。

为了使谓词在真值表上起作用,您需要将(1 OR 2) AND 3 转换为(SELF[1]==YES OR SELF[2]==YES) AND SELF[3]==YES 格式。你可以用正则表达式来做到这一点:

NSString *combine = @"(1 OR 2) AND 3";
NSError *err;
NSRegularExpression *regex = [NSRegularExpression
    regularExpressionWithPattern:@"\\d+"
    options:0
    error:&err];
NSString *subst = [regex
    stringByReplacingMatchesInString:combine
    options:0
    range:NSMakeRange(0, combine.length)
    withTemplate:@"SELF[$0]==YES"];
NSLog(@"%@", subst);

接下来,你可以构建NSPredicate

NSPredicate *pred = [NSPredicate predicateWithFormat:subst];

最后,你需要建立你的真值表。逐一评估谓词,并将结果放入NSArray。将未使用的元素放在索引 0 处,因为您的替换字符串使用从 1 开始的索引。

现在您可以使用之前准备的谓词了:

NSArray *data1 = @[@(NO), @(YES), @(NO), @(YES)];
NSArray *data2 = @[@(NO), @(NO), @(NO), @(YES)];
NSLog(@"%d", [pred evaluateWithObject:data1]); // Prints 1
NSLog(@"%d", [pred evaluateWithObject:data2]); // Prints 0

我为真值表data1data2 使用了固定值。您需要评估谓词pred1..predN,并将结果放入NSArray 的位置1..N。

【讨论】:

对不起,我在 NSPredicate *pred = [NSPredicate predicateWithFormat:subst];之后没看懂; NSPredicate pred = [NSPredicate predicateWithFormat:subst]; NSMutableArray *resultArray = [NSMutableArray new]; [resultArray addObject:@(NO)]; NSPredicate *currentPred1 = *; NSPredicate *currentPred2 = *; NSPredicate *currentPred3 =]; NSArray *arrayPredicates = @[currentPred1, currentPred2, currentPred3]; for (int i = 0; i @Alexander 这几乎是对的,除了 `[resultArray addObject:@([pred evaluateWithObject:arrayPredicates[i]])]` 应该是 [resultArray addObject:@([arrayPredicates[i] evaluateWithObject:someObject])],其中 someObject 是您传递的对象到您的pred1..predN 进行评估。 for 循环也需要 i < arrayPredicates.count,而不仅仅是 i < arrayPredicates Да,спасибобольшое! Попробовал вас найти, хотел с вами связаться, по почте например, но не получилось。【参考方案3】:

您可以使用以下代码:

NSPredicate *p1 = [NSPredicate ];


NSPredicate *p2 = [NSPredicate "];

NSPredicate *p3 = [NSPredicate "];

在最终谓词中

    NSPredicate *p = [NSCompoundPredicate andPredicateWithSubpredicates: @[p1, p2,p3]];

这个工作就像 (p1 AND p2 AND p3)

你也可以使用 orPredicateWithSubpredicates,notPredicateWithSubpredicate 和 nscompoundpredicate

【讨论】:

以上是关于复合谓词 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift 复合谓词

复合谓词不返回结果

谓词复合

XPath - 复合谓词 + 测试值是不是不以某事开头

快速,在具有复合谓词的提取结果控制器中找不到实体的键路径

Oracle 复合索引设计原理——前缀性和可选性