I am trying to figure out how to implement this in Objective-C.
I want to remove the strings in an NSArray
that have appear more than once in the array.
At the end I want to have an array that only has the unique lines in an array (meaning that not just the duplicates are deleted but also the original string that matches the duplicates.)
For example if you had the following array:
NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];
I would want the new array to look like this:
@"bob", @"frank", @"fred"
Use an NSCountedSet
:
NSCountedSet *countedSet = [NSCountedSet setWithArray:yourArray];
NSMutableArray *finalArray = [NSMutableArray arrayWithCapacity:[yourArray count]];
for(id obj in countedSet) {
if([countedSet countForObject:obj] == 1) {
[finalArray addObject:obj];
}
}
@Caleb suggested adding a method to NSCountedSet
called -objectsWithCount:,
, which I've implemented here:
@interface NSCountedSet (JRCountedSetAdditions)
- (NSArray *) objectsWithCount:(NSUInteger) count;
@end
@implementation NSCountedSet (JRCountedSetAdditions)
- (NSArray *) objectsWithCount:(NSUInteger) count {
NSMutableArray *array = [NSMutableArray array];
for(id obj in self) {
if([self countForObject:obj] == count) {
[array addObject:obj];
}
}
return [array copy];
}
@end
Once that's done, all you need is one line:
NSArray *finalArray = [[NSCountedSet setWithArray:yourArray] objectsWithCount:1];
By the way, this is type-agnostic, so this will work with any Objective-C object. :-)
One liner : uniqueArray = [[NSSet setWithArray:duplicateArray] allObjects];
if you don't care about the ordering :D
A slightly different approach from Jacob's:
NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];
NSCountedSet *namesSet = [[NSCountedSet alloc] initWithArray:array];
NSMutableArray *namesArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[namesSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
if ([namesSet countForObject:obj] == 1) {
[namesArray addObject:obj];
}
}];
And
NSLog(@"old: %@\nNew: %@", array, namesArray);
gives:
2011-06-16 18:10:32.783 SetTest[1756:903] old: (
bob,
frank,
sarah,
sarah,
fred,
corey,
corey
)
New: (
frank,
fred,
bob
)
Blocks are your friends! And since NSCountedSet
is a subclass of NSSet
you can use the block methods that are available there.
Here is the simplest approach to remove duplicate strings:
NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];
NSArray *distintStrings = [array valueForKeyPath:@"@distinctUnionOfObjects.self"];
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