¿La mejor manera de eliminar valores duplicados ( NSString
) NSMutableArray
en Objective-C?
¿Es esta la forma más fácil y correcta de hacerlo?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Teo Choong Ping
fuente
fuente
Respuestas:
Su
NSSet
enfoque es el mejor si no está preocupado por el orden de los objetos, pero, de nuevo, si no está preocupado por el orden, ¿por qué no los está almacenandoNSSet
para empezar?Escribí la respuesta a continuación en 2009; en 2011, Apple agregó
NSOrderedSet
a iOS 5 y Mac OS X 10.7. Lo que había sido un algoritmo ahora son dos líneas de código:Si le preocupa el pedido y está ejecutando iOS 4 o anterior, repita una copia de la matriz:
fuente
[NSOrderedSet orderedSetWithArray:array];
Puede recuperar una matriz a través dearray = [orderedSet allObjects];
o simplemente usarNSOrderedSet
s en lugar deNSArray
en primer lugar.[orderedSet allObjects]
con[orderedSet array]
!NSArray
y debemos crear tempNSMutableArray
. En su ejemplo, usted trabaja al revésNSSet
) o @Simon Whitaker enlace evitan antes de añadir valor duplicado que es la forma eficiente?Sé que esta es una vieja pregunta, pero hay una forma más elegante de eliminar duplicados en un
NSArray
si no te importa el pedido .Si usamos operadores de objetos de la codificación de valor clave , podemos hacer esto:
Como también señaló AnthoPak , es posible eliminar duplicados en función de una propiedad. Un ejemplo sería:
@distinctUnionOfObjects.name
fuente
@distinctUnionOfObjects.property
para eliminar duplicados por propiedad de una matriz de objetos personalizados. Por ejemplo@distinctUnionOfObjects.name
Sí, usar NSSet es un enfoque sensato.
Para agregar a la respuesta de Jim Puls, aquí hay un enfoque alternativo para eliminar los duplicados mientras se mantiene el orden:
Es esencialmente el mismo enfoque que el de Jim, pero copia elementos únicos en una nueva matriz mutable en lugar de eliminar duplicados del original. Esto hace que sea un poco más eficiente en memoria en el caso de una gran matriz con muchos duplicados (no es necesario hacer una copia de toda la matriz), y en mi opinión es un poco más legible.
Tenga en cuenta que, en cualquier caso, verificar si un elemento ya está incluido en la matriz de destino (usando
containsObject:
en mi ejemplo, oindexOfObject:inRange:
en el de Jim) no escala bien para grandes matrices. Esas comprobaciones se ejecutan en tiempo O (N), lo que significa que si duplica el tamaño de la matriz original, cada comprobación tardará el doble de tiempo en ejecutarse. Como está haciendo la verificación de cada objeto en la matriz, también ejecutará más de esas verificaciones más costosas. El algoritmo general (tanto el mío como el de Jim) se ejecuta en tiempo O (N 2 ), que se vuelve caro rápidamente a medida que crece la matriz original.Para reducir el tiempo a O (N), puede usar a
NSMutableSet
para almacenar un registro de elementos ya agregados a la nueva matriz, ya que las búsquedas de NSSet son O (1) en lugar de O (N). En otras palabras, verificar si un elemento es miembro de un NSSet toma el mismo tiempo, independientemente de cuántos elementos haya en el conjunto.El código que usa este enfoque se vería así:
Sin embargo, esto todavía parece un poco derrochador; todavía estamos generando una nueva matriz cuando la pregunta dejó en claro que la matriz original es mutable, por lo que deberíamos poder eliminarla en su lugar y ahorrar algo de memoria. Algo como esto:
ACTUALIZACIÓN : Yuri Niyazov señaló que mi última respuesta en realidad se ejecuta en O (N 2 ) porque
removeObjectAtIndex:
probablemente se ejecuta en tiempo O (N).(Dice "probablemente" porque no sabemos con certeza cómo se implementa; pero una posible implementación es que después de eliminar el objeto en el índice X, el método recorre cada elemento desde el índice X + 1 hasta el último objeto en la matriz , moviéndolos al índice anterior. Si ese es el caso, entonces ese es el rendimiento O (N).)
¿Entonces lo que hay que hacer? Depende de la situación. Si tiene una matriz grande y solo espera una pequeña cantidad de duplicados, la desduplicación en el lugar funcionará bien y le ahorrará tener que construir una matriz duplicada. Si tiene una matriz donde espera muchos duplicados, entonces construir una matriz separada y duplicada es probablemente el mejor enfoque. La conclusión aquí es que la notación big-O solo describe las características de un algoritmo, no le dirá definitivamente cuál es el mejor para cualquier circunstancia.
fuente
Si está apuntando a iOS 5+ (lo que cubre todo el mundo de iOS), mejor uso
NSOrderedSet
. Elimina duplicados y conserva el orden de suNSArray
.Solo haz
Ahora puede volver a convertirlo en una matriz NSA única
O simplemente use el setSet ordenado porque tiene los mismos métodos como un NSArray
objectAtIndex:
,firstObject
y así sucesivamente.Una verificación de membresía
contains
es aún más rápida en loNSOrderedSet
que sería en unNSArray
Para obtener más información, consulte la referencia NSOrderedSet
fuente
Disponible en OS X v10.7 y posterior.
Si está preocupado por el pedido, la forma correcta de hacerlo
Aquí está el código para eliminar valores duplicados de NSArray en orden.
fuente
necesita orden
o no necesita orden
fuente
Aquí eliminé valores de nombre duplicados de mainArray y almacené el resultado en NSMutableArray (listOfUsers)
fuente
Tenga en cuenta que si tiene una matriz ordenada, no necesita verificar con cada otro elemento de la matriz, solo con el último elemento. Esto debería ser mucho más rápido que verificar todos los artículos.
Parece que las
NSOrderedSet
respuestas que también se sugieren requieren mucho menos código, pero siNSOrderedSet
por alguna razón no puede usar una y tiene una matriz ordenada, creo que mi solución sería la más rápida. No estoy seguro de cómo se compara con la velocidad de lasNSOrderedSet
soluciones. También tenga en cuenta que mi código está comprobandoisEqualToString:
, por lo que la misma serie de letras no aparecerá más de una veznewArray
. No estoy seguro de si lasNSOrderedSet
soluciones eliminarán duplicados según el valor o la ubicación de la memoria.Mi ejemplo supone que
sortedSourceArray
contiene soloNSString
s, soloNSMutableString
s o una mezcla de los dos. Si en susortedSourceArray
lugar contiene soloNSNumber
s o soloNSDate
s, puede reemplazarcon
y debería funcionar perfectamente. Si
sortedSourceArray
contiene una mezcla deNSString
s,NSNumber
sy / oNSDate
s, probablemente se bloqueará.fuente
Hay un operador de objetos KVC que ofrece una solución más elegante.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Aquí hay una categoría NSArray .fuente
Una forma más simple de probar que no agregará valor duplicado antes de agregar un objeto en la matriz: -
// Supongamos que mutableArray está asignado e inicializado y contiene algún valor
fuente
Eliminar valores duplicados de NSMutableArray en Objective-C
fuente
Aquí está el código para eliminar valores duplicados de NSMutable Array. Funcionará para usted. myArray es su matriz mutable que desea eliminar valores duplicados.
fuente
Usar
Orderedset
hará el truco. Esto mantendrá la eliminación de duplicados de la matriz y mantendrá el orden que normalmente no funcionafuente
solo usa este código simple:
dado que nsset no permite valores duplicados y todos los objetos devuelven una matriz
fuente
NSOrderedSet
lugar deNSSet
.