用于按属性过滤掉类似对象的谓词

时间:2013-06-25 20:20:49

标签: iphone objective-c core-data nspredicate

我执行常规NSFetchRequest而没有任何谓词来获取100个托管对象(航班),每个Flight实体都有一个名为NSString的属性(flightCode)和此属性并不是唯一的,因此2个飞行物体可能具有相同的flightCode。 但是,我想通过从相似性中只乘一次飞行来获取所有具有相同flightCode的航班的飞行物体,即

如果获取请求返回5个航班,如下所示:

flight1:flightCode = ABC

flight2:flightCode = AA

flight3:flightCode = ABC

flight4:flightCode = ABC

flight5:flightCode = DEF

然后,获取请求必须过滤掉具有flightCode ABC的3个航班中的任意两个,并且只接受这3个中任意一个。

此过滤所需的NSPredicate是什么?

P.S。航班:1,3& 4可能与其他属性不同,即flight1的名称可能与flight3的名称不同。

提前感谢。

2 个答案:

答案 0 :(得分:1)

如果您只想要所有不同航班代码的列表,可以按照自己的意愿行事:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Flight"
    inManagedObjectContext:moc];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity.name];
request.resultType = NSDictionaryResultType;
request.returnsDistinctResults = YES;
request.propertiesToFetch = @[ entity.propertiesByName[@"flightCode"] ];

请注意,returnsDistinctResults仅在设置propertiesToFetch时有效,propertiesToFetch仅在resultTypeNSDictionaryResultType时有效。

REVISED

如果您想要完整的Flight个对象,但每个不同的航班代码只需要一个,我不认为您可以直接执行此操作。也许你可以要求对象ID和航班代码,按航班代码分组,并获取最小对象ID,以获得每个航班代码的一个对象ID。然后,您可以使用托管对象上下文中的objectForID:逐个将这些对象ID转换为完整对象。我会尝试这样的事情:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Flight"
    inManagedObjectContext:moc];

NSExpressionDescription *objectIDProperty = [[NSExpressionDescription alloc] init];
objectIDProperty.name = @"objectID";
objectIDProperty.expression = [NSExpression expressionForFunction:@"min:"
    arguments:@[ [NSExpression expressedForEvaluatedObject] ]];
objectIdProperty.expressionResultType = NSObjectIDAttributeType;

NSAttributeDescription *flightCodeProperty = entity.propertiesByName[@"flightCode"];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity.name];
request.resultType = NSDictionaryResultType;
request.returnsDistinctResults = YES;
request.propertiesToFetch = @[ flightCodeProperty, objectIDProperty ];

request.propertiesToGroupBy = @[ flightCodeProperty ];

我从this answer中榨取了很多。我不知道它是否有效,或者我是否在正确的轨道上。如果它完全运行,但没有给出正确的输出,请记住,通过添加-com.apple.CoreData.SQLDebug 1作为命令行参数,您可以看到它正在执行的SQL。

答案 1 :(得分:0)

您需要为所有航班设置NSMuteableArray,然后单独NSMuteableArray以跟踪您已经看过哪些元素

伪代码:

NSMuteablearray flights
NSMuteablearray alreadySeen


for (item in flights) {
if (alreadySeen containsObject:item)
     flights removeObject:item
else
     alreadySeen addObject:item

}