2011-09-30 2 views
3

У меня есть два nssets.Как сравнить два набора NSS на основе атрибутов объектов?

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 

Эти объекты с одинаковым идентификатором в этих двух наборах разные объекты, поэтому я не мог просто сделать 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) 

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

ответ

5

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

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]]; 
+0

это выглядит goot, но я получаю сообщение об ошибке «причина:» Невозможно проанализировать строку формата «objectID NOT IN% @» «я использовал' objectID », потому что это настоящее имя атрибута этих объектов. все перед фильтрацией, прежде чем выглядит красиво, я получаю идентификаторы и так далее. Есть идеи? – choise

+0

Я сожалею, что не тестировал свой ответ раньше. В [Predicate Programming Guide] (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html) указано, что оператор 'NOT' применяется ко всему выражению (и а не другой оператор, например, оператор 'IN'), поэтому мы должны написать' NOT objectID IN% @ 'вместо' objectID NOT IN% @ '. Я обновил свой ответ соответственно. – AliSoftware

+0

да также получил его с 'NOT (objectID IN% @)' я думаю – choise

8

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

Другой подход заключается в том, чтобы спросить, должны ли два человека с одинаковым идентификатором всегда считаться эквивалентными. Если это так, то вы можете переопределить isEqual: и hash для лица класса, как это (предполагается, что 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 имеет широкомасштабные удары, поэтому вам необходимо убедиться, что каждый объект, где вы сталкиваетесь с двумя объектами с одним и тем же идентификатором, должен рассматриваться как равный. Но если это так, это значительно упрощает и ускоряет работу вашего кода.

 Смежные вопросы

  • Нет связанных вопросов^_^