Удалите все строки с дубликатами в NSArray
Я пытаюсь понять, как реализовать это в Objective-C.
Я хочу удалить строки в NSArray
, которые несколько раз появлялись в массиве.
В конце я хочу иметь массив, который имеет только уникальные строки в массиве (это означает, что удалены не только дубликаты, но и исходная строка, которая соответствует дубликатам.)
Например, если у вас был следующий массив:
NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];
Я хочу, чтобы новый массив выглядел так:
@"bob", @"frank", @"fred"
Ответы
Ответ 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"];