Лучший способ удалить дубликаты значений ( NSString
) NSMutableArray
в Objective-C?
Это самый простой и правильный способ сделать это?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Тео Чунг Пинг
источник
источник
Ответы:
Ваш
NSSet
подход является лучшим, если вы не беспокоитесь о порядке объектов, но опять же, если вы не беспокоитесь о порядке, то почему вы не храните их вNSSet
начале?Я написал ответ ниже в 2009 году; В 2011 году Apple добавила
NSOrderedSet
iOS 5 и Mac OS X 10.7. То, что раньше было алгоритмом, теперь представляет собой две строки кода:Если вас беспокоит порядок, и вы работаете на iOS 4 или более ранней версии, переберите копию массива:
источник
[NSOrderedSet orderedSetWithArray:array];
Вы можете затем вернуть массив черезarray = [orderedSet allObjects];
или просто использоватьNSOrderedSet
s вместоNSArray
первого.[orderedSet allObjects]
на[orderedSet array]
!NSArray
и должны создавать временныеNSMutableArray
. В вашем примере вы работаете наоборотNSSet
) или ссылка @Simon Whitaker предотвращают перед добавлением дубликатов, что является эффективным способом?Я знаю, что это старый вопрос, но есть более элегантный способ удалить дубликаты,
NSArray
если вы не заботитесь о порядке .Если мы используем объектные операторы из Key Value Coding, мы можем сделать это:
Как отметил AnthoPak, можно удалить дубликаты на основе свойства. Примером может быть:
@distinctUnionOfObjects.name
источник
@distinctUnionOfObjects.property
для удаления дубликатов по свойству массива пользовательских объектов. Например@distinctUnionOfObjects.name
Да, использование NSSet - разумный подход.
Чтобы добавить к ответу Джима Пулса, вот альтернативный подход к удалению дубликатов при сохранении порядка:
По сути, это тот же подход, что и у Джима, но он копирует уникальные элементы в новый изменяемый массив, а не удаляет дубликаты из оригинала. Это делает его немного более эффективным в отношении памяти в случае большого массива с большим количеством дубликатов (не нужно делать копию всего массива) и, на мой взгляд, немного более читабельным.
Обратите внимание, что в любом случае проверка того, включен ли элемент в целевой массив (используется
containsObject:
в моем примере илиindexOfObject:inRange:
в Jim's), плохо масштабируется для больших массивов. Эти проверки выполняются за время O (N), что означает, что если вы удвоите размер исходного массива, то для каждой проверки потребуется вдвое больше времени. Так как вы делаете проверку для каждого объекта в массиве, вы также будете выполнять больше этих более дорогих проверок. Общий алгоритм (как мой, так и Джима) выполняется за время O (N 2 ), что быстро растет с ростом исходного массива.Чтобы получить это время O (N), вы можете использовать a
NSMutableSet
для хранения записи элементов, уже добавленных в новый массив, так как NSSet ищет O (1), а не O (N). Другими словами, проверка того, является ли элемент членом NSSet, занимает одно и то же время, независимо от того, сколько элементов в наборе.Код, использующий этот подход, будет выглядеть примерно так:
Это все еще кажется немного расточительным; мы все еще генерируем новый массив, когда вопрос прояснил, что исходный массив является изменяемым, поэтому мы должны иметь возможность его дедупликации и сэкономить память. Что-то вроде этого:
ОБНОВЛЕНИЕ : Юрий Ниязов указал, что мой последний ответ на самом деле работает в O (N 2 ), потому что,
removeObjectAtIndex:
вероятно, работает в O (N) времени.(Он говорит «вероятно», потому что мы не знаем наверняка, как это реализовано; но одна из возможных реализаций состоит в том, что после удаления объекта с индексом X метод затем проходит по каждому элементу от индекса X + 1 до последнего объекта в массиве , перемещая их в предыдущий индекс. Если это так, то это действительно производительность O (N).)
Так что делать? Это зависит от ситуации. Если у вас большой массив и вы ожидаете только небольшое количество дубликатов, то дедупликация на месте будет работать нормально и избавит вас от необходимости создавать дублирующий массив. Если у вас есть массив, в котором вы ожидаете много дубликатов, то, вероятно, лучше всего создать отдельный дедуплицированный массив. Вывод здесь заключается в том, что нотация big-O описывает только характеристики алгоритма, он не будет однозначно сообщать вам, какой вариант лучше всего подходит для любого конкретного обстоятельства.
источник
Если вы нацелены на iOS 5+ (что охватывает весь мир iOS), лучше всего использовать
NSOrderedSet
. Он удаляет дубликаты и сохраняет ваш порядокNSArray
.Просто сделать
Теперь вы можете преобразовать его обратно в уникальный NSArray
Или просто используйте orderSet, потому что он имеет те же методы, что и NSArray
objectAtIndex:
,firstObject
и так далее.Проверка членства с помощью
contains
еще быстрее,NSOrderedSet
чем наNSArray
Для дополнительной проверки NSOrderedSet Ссылка
источник
Доступный в OS X v10.7 и позже.
Если вы беспокоитесь о заказе, правильный способ сделать
Вот код удаления значений дубликатов из NSArray в порядке.
источник
нужен заказ
или не нужен заказ
источник
Здесь я удалил повторяющиеся значения имени из mainArray и сохранил результат в NSMutableArray (listOfUsers)
источник
Обратите внимание, что если у вас есть отсортированный массив, вам не нужно проверять все остальные элементы в массиве, только последний элемент. Это должно быть намного быстрее, чем проверка по всем пунктам.
Похоже, что для
NSOrderedSet
ответов, которые также предлагаются, требуется гораздо меньше кода, но еслиNSOrderedSet
по какой-то причине вы не можете использовать его , и у вас есть отсортированный массив, я считаю, что мое решение будет самым быстрым. Я не уверен, как это сравнивается со скоростьюNSOrderedSet
решений. Также обратите внимание, что мой код проверяетсяisEqualToString:
, поэтому одна и та же серия букв не будет появляться более одного разаnewArray
. Я не уверен, чтоNSOrderedSet
решения удалят дубликаты на основе значения или в зависимости от места в памяти.В моем примере предполагается, что
sortedSourceArray
содержит толькоNSString
s, простоNSMutableString
s или их комбинацию. ЕслиsortedSourceArray
вместо этого содержит толькоNSNumber
s или простоNSDate
s, вы можете заменитьс участием
и это должно работать отлично. Если
sortedSourceArray
содержит смесьNSString
s,NSNumber
s и / илиNSDate
s, он, вероятно, потерпит крах.источник
Есть оператор объектов KVC, который предлагает более элегантное решение.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Вот категория NSArray .источник
Еще один простой способ, который вы можете попробовать, который не добавит дубликат Value перед добавлением объекта в массив:
// Предположим, что mutableArray выделен и инициализирован и содержит некоторое значение
источник
Удалите повторяющиеся значения из NSMutableArray в Objective-C
источник
Вот код удаления значений дубликатов из NSMutable Array. Это будет работать для вас. myArray - это ваш изменяемый массив, который вы хотите удалить дублирующиеся значения.
источник
Использование
Orderedset
сделает свое дело. Это сохранит удаление дубликатов из массива и будет поддерживать порядок, который обычно не выполняетсяисточник
просто используйте этот простой код:
так как nsset не допускает повторяющихся значений и все объекты возвращают массив
источник
NSOrderedSet
застрахованныйNSSet
.