Как сравнить два NSSets на основе атрибутов объектов? - PullRequest
3 голосов
/ 30 сентября 2011

У меня есть два nssets.

nsset1: person.id = 1, person.id = 2, person.id = 3
nsset2: person.id = 1, person.id = 2

Результаты должны быть:

nsset1 - nsset2: person (with id 3)
nsset2 - nsset1: null

Эти объекты с одинаковым идентификатором в этих двух наборах являются разными объектами, поэтому я не мог простоdo minusSet.

Я хочу сделать что-то вроде:

nsset1: person.id = 1, person.id = 2, person.id = 3
nsset2: person.id = 4, person.id = 5

Результаты должны быть такими:

nsset1 - nsset2: person (id 1), person (id 2), person (id 3)
nsset2 - nsset1: person (id 4), person (id 5)

Каков наилучший способ сделать это?

Ответы [ 2 ]

8 голосов
/ 30 сентября 2011

@ Ответ AliSoftware - интересный подход. NSPredicate довольно медленно за пределами Core Data, но это часто хорошо. Если производительность является проблемой, вы можете реализовать тот же алгоритм с циклом, который состоит из нескольких строк кода, но, как правило, быстрее.

Другой подход заключается в том, чтобы спросить, всегда ли два человека с одинаковым идентификатором должны считаться эквивалентными. Если это так, тогда вы можете переопределить isEqual: и hash для своего класса person следующим образом (при условии, что identifier является NSUInteger):

- (BOOL)isEqual:(id)other {
  if ([other isMemberOfClass:[self class]) {
    return ([other identifier] == [self identifier]);
  }
  return NO;
}

- (NSUInteger)hash {
  return [self identifier];
}

При этом все операции NSSet будут обрабатывать объекты с одинаковым идентификатором как равные, поэтому вы можете использовать minusSet. Также NSMutableSet addObject: автоматически будет уникальным для вас по идентификатору.

Реализация isEqual: и hash имеет далеко идущие последствия, поэтому вам нужно убедиться, что везде, где вы встречаете два объекта человека с одинаковым идентификатором, они должны рассматриваться как равные. Но если это ваш случай, это значительно упрощает и ускоряет ваш код.

5 голосов
/ 30 сентября 2011

Вы должны попробовать что-то вроде этого

NSSet* nsset1 = [NSSet setWithObjects:person_with_id_1, person_with_id_2, person_with_id_3, nil];
NSSet* nsset2 = [NSSet setWithObjects:person_with_id_2, person_with_id_4, nil];

// retrieve the IDs of the objects in nsset2
NSSet* nsset2_ids = [nsset2 valueForKey:@"objectID"]; 
// only keep the objects of nsset1 whose 'id' are not in nsset2_ids
NSSet* nsset1_minus_nsset2 = [nsset1 filteredSetUsingPredicate:
    [NSPredicate predicateWithFormat:@"NOT objectID IN %@",nsset2_ids]];
...