Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove all strings with duplicates in an NSArray

Tags:

objective-c

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"
like image 825
user801903 Avatar asked Jun 16 '11 16:06

user801903


4 Answers

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. :-)

like image 161
Jacob Relkin Avatar answered Nov 17 '22 05:11

Jacob Relkin


One liner : uniqueArray = [[NSSet setWithArray:duplicateArray] allObjects]; if you don't care about the ordering :D

like image 36
REALFREE Avatar answered Nov 17 '22 04:11

REALFREE


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.

like image 4
Abizern Avatar answered Nov 17 '22 05:11

Abizern


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"];
like image 2
Zulqarnain Mustafa Avatar answered Nov 17 '22 04:11

Zulqarnain Mustafa