Подтвердить что ты не робот

NSPredicate: выберите один из каждого типа

Я хочу создать NSFetchRequest для таких объектов:

Object - Car, который имеет attribute color. У меня четыре машины:

car1.color = red
car2.color = red
car3.color = blue
car4.color = green

Я хочу создать NSPredicate, который выбирает только один автомобиль для каждого цвета (неважно, какой автомобиль он выбирает.

Как я могу это достичь?

На самом деле я ищу что-то похожее на DISTINCT в SQL

4b9b3361

Ответ 1

Core Data поддерживает выборку различных значений. Apple даже предоставляет пример кода здесь: http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/fetchExpressions.html


С этой страницы:

Извлечение отличительных значений

Чтобы получить уникальные значения определенного атрибута во всех экземпляров данного объекта, вы настраиваете запрос на выборку с помощью метод setReturnsDistinctResults: (и передать YES в качестве параметра). Вы также укажите, что выборка должна возвращать словари, а не управляемые объекты и имя свойства, которое вы хотите получить.

Swift 2.0

let context:NSManagedObjectContext! = <#Get the context#>
let entity = NSEntityDescription.entityForName( "<#Entity name#>",  inManagedObjectContext:context )
let request = NSFetchRequest()
request.entity = entity
request.resultType = .DictionaryResultType
request.returnsDistinctResults = true
request.propertiesToFetch = [ "<#Attribute name#>" ]

var objects:[[String:AnyObject]]?
do
{
    try objects = context.executeFetchRequest( request )
}
catch
{
    // handle failed fetch
}

Obj-C

NSManagedObjectContext *context = <#Get the context#>;  

NSEntityDescription *entity = [NSEntityDescription  entityForName:@"<#Entity name#>" inManagedObjectContext:context];  
NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
[request setEntity:entity]; 
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES]; 
[request setPropertiesToFetch:@[@"<#Attribute name#>"]];  

// Execute the fetch. 

NSError *error = nil; 
id requestedValue = nil; 
NSArray *objects = [context executeFetchRequest:request error:&error]; 
if (objects == nil) {
    // Handle the error. 
} 

(Один "полученный" заключается в том, что результаты будут возвращены в виде словарей - если вам нужны объекты, которые вы можете сделать еще один выбор, чтобы получить их по ID)

Ответ 2

Вы пытались использовать valueForKeyPath? Вы можете сделать что-то подобное в массиве, который предоставляет вам NSPredicate.

NSArray* distinctColors = [cars valueForKeyPath:@"@distinctUnionOfObjects.color"];

Он вернет вам определенные цвета, которые у вас есть, я не знаю, если это то, что вы хотите, но с цветами вы можете сделать что-то вроде @Anupdas:

Ответ 3

Если вы настроите iOS 4.0 или новее и не используете SQL-хранилище Core-Data, почему бы не использовать predicateWithBlock:?

Ниже вы создадите NSFetchRequest, который вы хотите.

- (NSFetchRequest*) fetchRequestForSingleInstanceOfEntity:(NSString*)entityName groupedBy:(NSString*)attributeName
{
  __block NSMutableSet *uniqueAttributes = [NSMutableSet set];

  NSPredicate *filter = [NSPredicate predicateWithBlock:^(id evaluatedObject, NSDictionary *bindings) {
    if( [uniqueAttributes containsObject:[evaluatedObject valueForKey:attributeName]] )
      return NO;

    [uniqueAttributes addObject:[evaluatedObject valueForKey:attributeName]];
    return YES;
  }];

  NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName:entityName];
  req.predicate = filter;

  return req;
}

Затем вы можете создать новый метод для выполнения выборки и возврата желаемых результатов.

- (NSArray*) fetchOneInstanceOfEntity:(NSString*)entityName groupedBy:(NSString*)attributeName
{
  NSFetchRequest *req = [self fetchRequestForSingleInstanceOfEntity:entityName groupedBy:attributeName];

  // perform fetch
  NSError *fetchError = nil;
  NSArray *fetchResults = [_context executeFetchRequest:req error:&fetchError];

  // fetch results
  if( !fetchResults ) {
    // Handle error ...
    return nil;
  }

  return fetchResults;
}

Ответ 4

Вы смотрите что-то вроде этого

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Car"];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"color ==  %@",@"green"]];
[fetchRequest setFetchLimit:1];

NSError *error = nil;
NSArray *fetchedCars = [context executeFetchRequest:fetchRequest error:&error];

Car *car = [fetchedCars lastObject];

if(!car){
    //Handle the error
}

Ответ 5

попробуйте следующее:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:@"Selected_data"
            inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *predicatecnName = [NSPredicate predicateWithFormat:@"countries contains[cd] %@", Countryid];
NSPredicate *predicateLn = [NSPredicate predicateWithFormat:@"languages contains[cd] %@", languageid];
NSArray *subPredicates = [NSArray arrayWithObjects:predicatecnName, predicateLn, nil];

NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];


[request setPredicate:predicate];
NSMutableArray *sendfd=[[NSMutableArray alloc] init];
NSError *error;
NSArray *array1 = [self.managedObjectContext executeFetchRequest:request error:&error];


if (array1 != nil) {


    for (Selected_data *sld in array1)
    {

        [sendfd addObject:sld.providers];
    }


}
else {

}
return sendfd;

Ответ 6

попробуйте следующее:

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Cars"];
    NSArray *arrayValues = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

if (arrayValues.count != 0) {
     NSDictionary *result = [NSDictionary dictionaryWithObjects:arrayValues
                           forKeys:[arrayValues valueForKey:@"color"]];
     return [result allValues];
}