Objective c 如何使用;“全部”;NSPredicate中用于筛选基于CoreData的集合的聚合操作
基于下面的数据模型 根据用户输入,我创建了一个名为selectedTags的实体标记的managedObjects的NSSetObjective c 如何使用;“全部”;NSPredicate中用于筛选基于CoreData的集合的聚合操作,objective-c,ios,core-data,nspredicate,Objective C,Ios,Core Data,Nspredicate,基于下面的数据模型 根据用户输入,我创建了一个名为selectedTags的实体标记的managedObjects的NSSet 我的问题是: 。。。这将返回在selectedTags集中至少有一个entryTag的任何条目 我想要一些大致如下的东西: [NSPredicate predicateWithFormat:@"ALL entryTags IN %@", selectedTags]; 。。。请注意,唯一的更改是将“ANY”改为“ALL”。这说明了我想要什么,但不起作用 为了制定结果
我的问题是: 。。。这将返回在selectedTags集中至少有一个entryTag的任何条目 我想要一些大致如下的东西:
[NSPredicate predicateWithFormat:@"ALL entryTags IN %@", selectedTags];
。。。请注意,唯一的更改是将“ANY”改为“ALL”。这说明了我想要什么,但不起作用
为了制定结果,我希望:
我正在寻找一种解决方案,它只返回所有entryTags都在selectedTags列表中的条目(但同时,如果可能的话,不一定相反)
进一步说明:
(标记)妈妈(标签)爸爸
(标签)礼物 (条目)她是一个她……(标签)妈妈
(条目)他是一个他……(标签)爸爸
(条目)给妈妈的礼物…(标签:)妈妈,礼物
(条目)给爸爸的礼物…(标签:)爸爸,礼物
如果selectedTags包含“妈妈”和“礼物”,则会显示条目“给爸爸的礼物”,因为它有标签“礼物”。我宁愿它不显示:)你不能用谓词做你想做的事
ANY
和ALL
运算符适用于被测试的实体(在本例中为Entry
),而不是集合的内容(selectedTags
)。任何一个操作符都将返回一个与集合的任何单个元素匹配的条目
对象。ANY
操作符将返回它找到的第一个匹配项,而ALL
操作符将返回所有匹配项。在这两种情况下,它们都不会返回与所提供集合中的每个元素匹配的条目
(看起来您还试图在selectedTags
中使用实际的Tag
对象。这很可能不起作用,因为在没有专用比较方法的类上进行对象比较通常会失败。速度也很慢。您需要比较谓词中的属性。)
由于您已经有了所需的标记
对象,要找到与候选对象相关的实体
对象,只需遍历标记.taggedEntries
关系即可。然后,您必须找到所有实体
对象集的交集,以仅查找与每个选定的标记
对象相关的实体
对象。因为没有intersect collections操作符,所以需要一个循环
if ([selectedEntries count]>=2) {
NSMutableSet *intersectEntries=[[NSMutableSet alloc] initWithCapacity:1];
for (int i=1; i<[selectedTags count]; i++) {
if ([intersectEntries count]==0) {
[intersectEntries unionSet:[[selectedEntries objectAtIndex:(i-1)] valueForKey:@"taggedEntries"]];
}
[intersectEntries intersectSet:[[selectedEntries objectAtIndex:i] valueForKey:@"taggedEntries"]];
}
}
if([selectedEntries count]>=2){
NSMutableSet*intersectEntries=[[NSMutableSet alloc]initWithCapacity:1];
对于(int i=1;i我意识到我可以在这里为我以前得到的指导提供一些东西。通过使用TechZen提供的代码,我能够得出以下代码——对我来说是非常宝贵的代码:
- (NSArray *)unionSetOfObjectsForObjects:(NSArray *)objects {
NSMutableSet *unionSetOfObjects = [NSMutableSet set];
if (objects.count)
[unionSetOfObjects unionSet:[[objects objectAtIndex:0] valueForKey:@"key"]];
//unionSetOfObjects = [[objects objectAtIndex:0] valueForKey:@"key"];
if (objects.count > 1)
for (id object in objects)
[unionSetOfObjects intersectSet:[object valueForKey:@"key"]];
return unionSetOfObjects.allObjects;
}
如果此代码的作用不明显:
它收集objects
数组中提供的所有对象上的键key
的所有值(在我的例子中是对象)
这段代码……味道不错,不是吗?使用复合谓词如何?据我所知,您希望返回与标记列表匹配的所有条目,而不仅仅是其中任何一个。一种方法是为每个标记创建一个谓词,然后使用复合谓词将它们组合在一起
NSMutableArray *predicates = [[NSMutableArray alloc] init];
for (Tag *tag in selectedTags) {
[predicates addObject:[NSPredicate predicateWithFormat:@"ANY entryTags.tagName MATCHES %@", tag.tagName]];
}
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
这应该可以满足您的需求。然后根据您的请求设置此谓词。这是到目前为止的明确答案:
[NSPredicate predicateWithFormat:@"SUBQUERY(entryTags, $tag, $tag IN %@).@count = %d", selectedTags, [selectedTags count]];
B-E-A-U-T-I-F-U-L
感谢戴夫·德隆。最简单的方法是:
[NSPredicate predicateWithFormat:@"entryTags IN %@", selectedTags];
您不需要ALL子句。此处还记录了该子句:
正如你在这篇文章中看到的,用户成功地做到了(阅读对原始问题的评论)
澄清:selectedTags
是另一个实体还是它是条目的属性或关系?entryTags
是属性还是关系?我一直在看你的答案,希望你能插话:我更新了问题。我不知道如何使用这个代码。想详细说明一下吗?我想返回所有条目对象,其中Entry.entryTags包含selectedTags中的所有标记对象。基本上,您想返回与您拥有的标记列表匹配的所有条目。因此,您为每个要匹配的标记编写一个谓词。因此,您的谓词类似于返回任何具有与此标记匹配的标记的条目ame。然后你和每个标记的所有谓词一起,得到所有结果的交集,即在selectedTags中包含所有标记的条目。我在上面编辑了我的答案,以使用你的变量名。非常干净的解决方案。对于普通obj c开发人员来说,比子查询谓词可读性好得多。这个答案在或者我,据我所知,我的需求与问题中所解释的相符。我不确定selectedTags是否必须是NSArray或NSSet,因此我对其进行了两种测试,其中一种都有效。这正是我所需要的,谢谢!(现在我也知道了子查询)
[NSPredicate predicateWithFormat:@"entryTags IN %@", selectedTags];