使用谓词过滤基于另一个数组的NSArray
考虑下面的数组。 数组包含“Alpha”types的对象。 我们只关心NSString
types的属性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性能代码