使用谓词过滤基于另一个数组的NSArray

考虑下面的数组。 数组包含“Alpha”types的对象。 我们只关心NSStringtypes的属性username

 NSArray *some_usernames = @[ <multiple values of type Alpha> ] NSArray *all_usernames = @[ <multiple values of type Alpha> ] 

我基本上想要所有的用户名不在数组some_usernames ,即

 NSArray *remaining_usernames = @[ <all_usernames but not in some_usernames> ]; 

我打算这样做的方式是:

 NSPredicates *predicates; for (Alpha *alpha in some_usernames) { predicate = [predicate with @"username != %@", alpha.username]; predicates.add(predicate) } create compound predicate filter all_usernames 

但是这样做感觉像是一个糟糕的方式。 有两种方法可以做到这一点? 我以前见过它,但是我不能指向代码引用了。

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]]; NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate]; 

完整的例子

 @interface Alpha : NSObject @property (nonatomic, copy) NSString *username; -(instancetype) initWithUsername:(NSString *)username; @end @implementation Alpha -(instancetype) initWithUsername:(NSString *)username { self = [super init]; if (self) { self.username = username; } return self; } -(NSString *)description{ return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username]; } @end NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"], [[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"z"], [[Alpha alloc] initWithUsername:@"f"], [[Alpha alloc] initWithUsername:@"e"]]; NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"f"]]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]]; NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate]; NSLog(@"%@", remaining_usernames); 

版画

 ( "Alpha: a", "Alpha: z", "Alpha: e" ) 

我想添加另一个答案:

如果对象的sorting是不需要的(而且 – 很可能 – 等于不需要的对象),则可以使用集合和算术设置来代替对数组使用谓词过滤。 要做到这一点,我们必须教导Alpha什么平等手段,并提供一个哈希方法 在这种情况下,我们只使用NSStrings实现:

 @implementation Alpha -(instancetype) initWithUsername:(NSString *)username { self = [super init]; if (self) { self.username = username; } return self; } -(NSString *)description{ return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username]; } -(BOOL)isEqual:(id)object { return [self.username isEqual:[object username]]; } -(NSUInteger)hash { return [self.username hash]; } @end NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"], [[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"z"], [[Alpha alloc] initWithUsername:@"f"], [[Alpha alloc] initWithUsername:@"e"]]; NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"f"]]; NSSet *allSet = [NSSet setWithArray:all_usernames]; NSSet *someSet = [NSSet setWithArray:some_usernames]; NSMutableSet *remainingSet = [allSet mutableCopy]; [remainingSet minusSet:someSet]; NSLog(@"%@", remainingSet); 

版画

 {( Alpha: z, Alpha: e, Alpha: a )} 

对于更多的数据,这个代码应该快得多。 请观看WWDC 2013:devise性能代码