Consider the arrays below. The arrays contain objects of type 'Alpha'. We only care about the property username
which is of type NSString
.
NSArray *some_usernames = @[ <multiple values of type Alpha> ]
NSArray *all_usernames = @[ <multiple values of type Alpha> ]
I basically want a list of all the usernames that are not in the array some_usernames
, i.e.
NSArray *remaining_usernames = @[ <all_usernames but not in some_usernames> ];
The way I would intend to do is:
NSPredicates *predicates;
for (Alpha *alpha in some_usernames)
{
predicate = [predicate with @"username != %@", alpha.username];
predicates.add(predicate)
}
create compound predicate
filter all_usernames
But this feels like a bad way of doing this. Is there a way to do this in two lines? I have seen it before but I can't point to the code reference anymore.
I want to add another answer:
If the ordering of the objects isn't needed (and — most likely — equal objects unwanted) you could instead of using predicate filtering on arrays use Sets and set arithmetic. To do so we must teach Alpha
what equality means and provide a hash method. In this case we just use NSStrings implementation:
@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);
prints
{(
Alpha: z,
Alpha: e,
Alpha: a
)}
This code should be much faster for more data. Please watch WWDC 2013: Designing Code for Performance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With