How to compare two NSSets based on attributes of objects?

本秂侑毒 提交于 2019-12-05 21:23:36

You should try something like this

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

@AliSoftware's answer is an interesting approach. NSPredicate is pretty slow outside of Core Data, but that often is fine. If the performance is a problem, you can implement the same algorithm with a loop, which is a few more lines of code, but generally faster.

Another approach is to ask whether two persons with the same ID should always be considered equivalent. If that's true, then you can override isEqual: and hash for your person class like this (assuming identifier is an NSUInteger):

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

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

Doing this, all NSSet operations will treat objects with the same identifier as equal, so you can use minusSet. Also NSMutableSet addObject: will automatically unique for you on identifier.

Implementing isEqual: and hash has broad-reaching impacts, so you need to make sure that everyplace you encounter two person objects with the same identifier, they should be treated as equal. But if that's you case, this does greatly simplify and speed up your code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!