La meilleure façon de supprimer les valeurs en double ( NSString
) NSMutableArray
dans Objective-C?
Est-ce la manière la plus simple et la plus appropriée de le faire?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Teo Choong Ping
la source
la source
Réponses:
Votre
NSSet
approche est la meilleure si vous ne vous inquiétez pas de l'ordre des objets, mais encore une fois, si vous ne vous inquiétez pas de l'ordre, alors pourquoi ne les stockez-vous pas dans unNSSet
pour commencer?J'ai écrit la réponse ci-dessous en 2009; en 2011, Apple a ajouté
NSOrderedSet
iOS 5 et Mac OS X 10.7. Ce qui avait été un algorithme est maintenant composé de deux lignes de code:Si vous vous inquiétez de la commande et que vous utilisez iOS 4 ou une version antérieure, parcourez une copie du tableau:
la source
[NSOrderedSet orderedSetWithArray:array];
Vous pouvez ensuite récupérer un tableau viaarray = [orderedSet allObjects];
ou simplement utiliserNSOrderedSet
s auNSArray
lieu de.[orderedSet allObjects]
par[orderedSet array]
!NSArray
et devrions créer des tempNSMutableArray
. Dans votre exemple, vous travaillez vice versaNSSet
) ou @Simon Whitaker lien empêchent ajouter avant doublon qui est de manière efficace?Je sais que c'est une vieille question, mais il existe un moyen plus élégant de supprimer les doublons
NSArray
si vous ne vous souciez pas de la commande .Si nous utilisons des opérateurs d'objets du codage de valeurs clés, nous pouvons le faire:
Comme AnthoPak l'a également noté, il est possible de supprimer les doublons en fonction d'une propriété. Un exemple serait:
@distinctUnionOfObjects.name
la source
@distinctUnionOfObjects.property
pour supprimer les doublons par propriété d'un tableau d'objets personnalisés. Par exemple@distinctUnionOfObjects.name
Oui, l'utilisation de NSSet est une approche judicieuse.
Pour ajouter à la réponse de Jim Puls, voici une approche alternative pour supprimer les doublons tout en conservant l'ordre:
C'est essentiellement la même approche que celle de Jim, mais copie les éléments uniques dans un nouveau tableau mutable plutôt que de supprimer les doublons de l'original. Cela le rend légèrement plus efficace dans le cas d'un grand tableau avec beaucoup de doublons (pas besoin de faire une copie de l'ensemble du tableau), et est à mon avis un peu plus lisible.
Notez que dans les deux cas, vérifier si un élément est déjà inclus dans le tableau cible (en utilisant
containsObject:
dans mon exemple, ouindexOfObject:inRange:
dans celui de Jim) ne s'adapte pas bien aux grands tableaux. Ces vérifications s'exécutent en temps O (N), ce qui signifie que si vous doublez la taille du tableau d'origine, chaque vérification prendra deux fois plus de temps à s'exécuter. Puisque vous effectuez la vérification pour chaque objet du tableau, vous exécuterez également plus de ces vérifications plus coûteuses. L'algorithme global (le mien et celui de Jim) s'exécute en temps O (N 2 ), ce qui devient vite coûteux à mesure que le tableau d'origine se développe.Pour ramener cela au temps O (N), vous pouvez utiliser a
NSMutableSet
pour stocker un enregistrement des éléments déjà ajoutés au nouveau tableau, car les recherches NSSet sont O (1) plutôt que O (N). En d'autres termes, vérifier si un élément est membre d'un NSSet prend le même temps, quel que soit le nombre d'éléments dans l'ensemble.Le code utilisant cette approche ressemblerait à ceci:
Cela semble néanmoins un peu inutile; nous sommes toujours en train de générer un nouveau tableau lorsque la question a clairement indiqué que le tableau d'origine est mutable, nous devrions donc être en mesure de le déduper en place et d'économiser de la mémoire. Quelque chose comme ça:
MISE À JOUR : Yuri Niyazov a souligné que ma dernière réponse s'exécute en fait en O (N 2 ) parce que
removeObjectAtIndex:
probablement en O (N).(Il dit "probablement" parce que nous ne savons pas avec certitude comment il est implémenté; mais une implémentation possible est qu'après avoir supprimé l'objet à l'index X, la méthode boucle ensuite sur chaque élément de l'index X + 1 au dernier objet du tableau , en les déplaçant vers l'index précédent. Si tel est le cas, il s'agit bien de la performance O (N).)
Alors que faire? Ça dépend de la situation. Si vous avez un grand tableau et que vous ne vous attendez qu'à un petit nombre de doublons, la déduplication sur place fonctionnera très bien et vous évitera d'avoir à créer un tableau en double. Si vous avez un tableau dans lequel vous vous attendez à beaucoup de doublons, la création d'un tableau séparé et déduppé est probablement la meilleure approche. Ce qu'il faut retenir ici, c'est que la notation big-O ne décrit que les caractéristiques d'un algorithme, elle ne vous dira pas définitivement ce qui est le mieux pour une circonstance donnée.
la source
Si vous ciblez iOS 5+ (ce qui couvre tout le monde iOS), meilleure utilisation
NSOrderedSet
. Il supprime les doublons et conserve l'ordre de votreNSArray
.Fais juste
Vous pouvez maintenant le reconvertir en un NSArray unique
Ou utilisez simplement le orderSet car il a les mêmes méthodes qu'un NSArray comme
objectAtIndex:
,firstObject
et ainsi de suite.Un chèque d'adhésion avec
contains
est encore plus rapide sur leNSOrderedSet
que ce serait sur uneNSArray
Pour plus d'informations, consultez la référence NSOrderedSet
la source
Disponible dans OS X v10.7 et versions ultérieures.
Si vous êtes inquiet pour la commande, bonne façon de faire
Voici le code de suppression des valeurs en double de NSArray dans l'ordre.
la source
besoin d'ordre
ou pas besoin de commande
la source
Ici, j'ai supprimé les valeurs de nom en double de mainArray et stocké le résultat dans NSMutableArray (listOfUsers)
la source
Notez que si vous avez un tableau trié, vous n'avez pas besoin de vérifier tous les autres éléments du tableau, juste le dernier élément. Cela devrait être beaucoup plus rapide que de vérifier tous les éléments.
Il semble que les
NSOrderedSet
réponses qui sont également suggérées nécessitent beaucoup moins de code, mais si vous ne pouvez pas utiliser unNSOrderedSet
pour une raison quelconque et que vous avez un tableau trié, je pense que ma solution serait la plus rapide. Je ne sais pas comment cela se compare à la vitesse desNSOrderedSet
solutions. Notez également que mon code est en cours de vérification avecisEqualToString:
, donc la même série de lettres n'apparaîtra pas plus d'une foisnewArray
. Je ne sais pas si lesNSOrderedSet
solutions supprimeront les doublons en fonction de la valeur ou de l'emplacement de la mémoire.Mon exemple suppose qu'il
sortedSourceArray
contient justeNSString
s, justeNSMutableString
s ou un mélange des deux. Si à lasortedSourceArray
place contient justeNSNumber
s ou justeNSDate
s, vous pouvez remplaceravec
et cela devrait fonctionner parfaitement. Si
sortedSourceArray
contient un mélange deNSString
s,NSNumber
s et / ouNSDate
s, il plantera probablement.la source
Il existe un opérateur d'objets KVC qui offre une solution plus élégante.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Voici une catégorie NSArray .la source
Une autre façon simple d'essayer qui n'ajoutera pas de valeur en double avant d'ajouter un objet dans le tableau: -
// Supposons que mutableArray est alloué et initialisé et contient une valeur
la source
Supprimer les valeurs en double de NSMutableArray dans Objective-C
la source
Voici le code de suppression des valeurs en double de NSMutable Array. .il fonctionnera pour vous. myArray est votre matrice mutable dont vous souhaitez supprimer les valeurs en double.
la source
L'utilisation
Orderedset
fera l'affaire. Cela gardera les doublons supprimés du tableau et maintiendra l'ordre ce que les ensembles ne font normalement pasla source
utilisez simplement ce code simple:
puisque nsset n'autorise pas les valeurs dupliquées et que tous les objets retournent un tableau
la source
NSOrderedSet
insteed ofNSSet
.