Подтвердить что ты не робот

Удалите все строки с дубликатами в NSArray

Я пытаюсь понять, как реализовать это в Objective-C.

Я хочу удалить строки в NSArray, которые несколько раз появлялись в массиве.

В конце я хочу иметь массив, который имеет только уникальные строки в массиве (это означает, что удалены не только дубликаты, но и исходная строка, которая соответствует дубликатам.)

Например, если у вас был следующий массив:

NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];

Я хочу, чтобы новый массив выглядел так:

@"bob", @"frank", @"fred"
4b9b3361

Ответ 1

Используйте 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 предложил добавить метод NSCountedSet под названием -objectsWithCount:,, который я реализовал здесь:

@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

После этого все, что вам нужно, это одна строка:

NSArray *finalArray = [[NSCountedSet setWithArray:yourArray] objectsWithCount:1];

Кстати, это тип-агностик, поэтому он будет работать с любым объектом Objective-C.: -)

Ответ 2

Один вкладыш: uniqueArray = [[NSSet setWithArray:duplicateArray] allObjects];, если вы не заботитесь о заказе: D

Ответ 3

Несколько иной подход из Джейкоба:

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];
    }
}];

И

NSLog(@"old: %@\nNew: %@", array, namesArray);

дает:

2011-06-16 18:10:32.783 SetTest[1756:903] old: (
    bob,
    frank,
    sarah,
    sarah,
    fred,
    corey,
    corey
)
New: (
    frank,
    fred,
    bob
)

Блоки - ваши друзья! И поскольку NSCountedSet является подклассом NSSet, вы можете использовать доступные ему методы блоков.

Ответ 4

Вот простой способ удаления повторяющихся строк:

NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];
NSArray *distintStrings = [array valueForKeyPath:@"@distinctUnionOfObjects.self"];