2010-10-24 15 views
11

J'ai un tableau avec des objets personnalisés. Chaque élément du tableau a un champ nommé "nom". Maintenant, je veux supprimer les entrées en double basées sur cette valeur de nom.Suppression des doublons d'un tableau dans l'objectif c

Comment dois-je procéder pour y parvenir.

Merci d'avance.

+0

sont les articles dans un récipient Objective-C comme NSArray, ou C/C++ (par exemple, std :: vecteur ou un tableau C)? –

+2

pourquoi le tag C? –

+0

désolé retiré la balise, son objectif c tableau avec des objets personnalisés ... "nom" est l'une de ses variables membres, je veux filtrer en fonction de cette valeur "nom". –

Répondre

9

Vous pourriez avoir à écrire effectivement cette méthode de filtrage vous:

@interface NSArray (CustomFiltering) 
@end 

@implementation NSArray (CustomFiltering) 

- (NSArray *) filterObjectsByKey:(NSString *) key { 
    NSMutableSet *tempValues = [[NSMutableSet alloc] init]; 
    NSMutableArray *ret = [NSMutableArray array]; 
    for(id obj in self) { 
     if(! [tempValues containsObject:[obj valueForKey:key]]) { 
      [tempValues addObject:[obj valueForKey:key]]; 
      [ret addObject:obj]; 
     } 
    } 
    [tempValues release]; 
    return ret; 
} 

@end 
+0

ce n'est pas un tableau de chaînes c'est un tableau d'objets personnalisé .... avec un nom de chaîne comme propriété ... Je veux filtrer basé dans ce nom propriété –

+0

Est-ce que le downvoter se soucie de commenter? –

+0

@Jacob: J'ai écrit ma réponse tout comme vous avez édité la vôtre. Vous devriez vraiment utiliser un 'NSMutableSet' au lieu d'un' NSMutableArray' pour les recherches, l'augmentation de performance d'une recherche de hachage est beaucoup mieux qu'une recherche linéaire. – PeyloW

27

Je ne sais pas d'aucune façon standard pour le faire fourni par les cadres. Donc vous devrez le faire en code. Quelque chose comme cela devrait être faisable:

NSArray* originalArray = ... // However you fetch it 
NSMutableSet* existingNames = [NSMutableSet set]; 
NSMutableArray* filteredArray = [NSMutableArray array]; 
for (id object in originalArray) { 
    if (![existingNames containsObject:[object name]]) { 
     [existingNames addObject:[object name]]; 
     [filteredArray addObject:object]; 
    } 
} 
+0

Merci PeyloW votre réponse était sur place ... Pouce en l'air ... Je vous souhaite bonne chance dans vos efforts .... –

+2

Ne devrait-il pas être [object objectForKey: @ "name"]; dans le côté de cette boucle? –

+0

aucun Skeater. C'est pour un NSDictionary. –

1

Si vous souhaitez que vos personnalisés sous-classes NSObject à être considérés comme égaux lorsque leurs noms sont égaux, vous pouvez mettre en œuvre isEqual: et hash. Cela vous permettra d'ajouter des objets à un NSSet/NSMutableSet (un ensemble d'objets distincts).

Vous pouvez ensuite facilement créer un NSArray trié en utilisant la méthode sortedArrayUsingDescriptors:.

MikeAsh a écrit une pièce assez solide sur l'implémentation de l'égalité personnalisée: Friday Q&A 2010-06-18: Implementing Equality and Hashing

1

Si vous êtes inquiet au sujet de l'ordre

NSArray * newArray = 
     [[NSOrderedSet orderedSetWithArray:oldArray] array]; **// iOS 5.0 and later** 
2

Je vais obtenir pare-balles pour cette ...

Vous pouvez convertir votre tableau dans un dictionnaire. Je ne sais pas à quel point cela est efficace, cela dépend de l'appel de l'implémentation et de la comparaison, mais il utilise une carte de hachage.

//Get unique entries 
NSArray *myArray = @[@"Hello", @"World", @"Hello"]; 
NSDictionary *uniq = [NSDictionary dictionaryWithObjects:myArray forKeys:myArray]; 
NSLog(@"%@", uniq.allKeys); 

* Remarque, cela peut changer l'ordre de votre choix.

+0

Hehehehe I LOVE this! –

+0

Edit: bien je viens de passer les 15 dernières minutes à corriger un bug dans mon code. L'utilisation de cette méthode NSDictionary ne conservera pas l'ORDER de votre tableau. Tous mes articles ont été brouillés. C'est ce que j'obtiens en utilisant hacky wordk-arounds où OP préface "Je vais avoir des flaks pour ça ..." lol –

7

Je sais que c'est une vieille question mais voici une autre possibilité, selon ce dont vous avez besoin.

Apple propose un moyen de le faire - Key-Value Coding Collection Operators.

Les opérateurs d'objet vous permettent d'agir sur une collection. Dans ce cas, vous voulez:

@distinctUnionOfObjects

L'opérateur @distinctUnionOfObjects retourne un tableau contenant les objets distincts dans la propriété spécifiée par le chemin de clé à droite de l'opérateur.

NSArray *distinctArray = [arrayWithDuplicatesvalueForKeyPath:@"@distinctUnionOfObjects.name"];

Dans votre cas, cependant, vous voulez que l'objet entier. Donc, ce que vous auriez à faire est double: 1) Utilisez @distinctUnionOfArrays à la place. Par exemple. Si vous avez ces objets personnalisés provenant d'autres collections, utilisez @distinctUnionOfArray.myCollectionOfObjects 2) Implémentez isEqual: sur ces objets pour les renvoyer si leur.le nom de sont égaux

0

Mettre en oeuvre isEqual pour faire vos objets comparables:

@interface SomeObject (Equality) 
@end 

@implementation SomeObject (Equality) 

- (BOOL)isEqual:(SomeObject*)other 
{ 
    return self.hash == other.hash; 
} 

- (NSUInteger)hash 
{ 
    return self.name;///your case 
} 

@end 

Comment utiliser:

- (NSArray*)distinctObjectsFromArray:(NSArray*)array 
{ 
    return [array valueForKeyPath:@"@distinctUnionOfObjects.self"]; 
} 
0

Il est assez simple dans une ligne

NSArray *duplicateList = ... 

Si vous ne vous souciez pas des éléments ordre alors (non ordonné)

NSArray *withoutDUP1 = [[NSSet setWithArray:duplicateList] allObjects]; 

maintenir les éléments dans l'ordre, puis (ordonnée)

NSArray *withoutDUP2 = [[NSOrderedSet orderedSetWithArray:duplicateList] array]; 
+0

Mais comment est le filtrage de code basé sur le champ "nom"? – Satyam