2010-10-24 2 views
11

Ho una matrice con oggetti personalizzati. Ogni elemento dell'array ha un campo chiamato "nome". Ora voglio rimuovere le voci duplicate in base a questo valore del nome.rimozione di duplicati dall'array nell'obiettivo c

Come devo fare per raggiungere questo.

Grazie in anticipo.

+0

sono gli elementi in un contenitore di Objective-C come NSArray, o C/C++ (per esempio, std :: vettore o un array C)? –

+2

perché il tag C? –

+0

sorry rimosso il tag, il suo array c oggettivo con oggetti personalizzati ... "nome" è una delle sue variabili membro, voglio filtrare in base a questo valore "nome". –

risposta

9

Potrebbe essere necessario effettivamente scrivere questo metodo di filtraggio da soli:

@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

non è un array di stringhe è un array di oggetti personalizzato .... con un nome di stringa come proprietà ... Voglio filtrare basato in questo nome proprietà –

+0

Il downtroter si preoccuperebbe di commentare? –

+0

@Jacob: ha scritto la mia risposta proprio come hai modificato la tua. Dovresti davvero usare un 'NSMutableSet' invece di un' NSMutableArray' per le ricerche, l'aumento delle prestazioni da una ricerca hash è molto meglio di una ricerca lineare. – PeyloW

27

non so di alcun modo standard per fare questo fornito dai quadri. Quindi dovrai farlo in codice. Qualcosa del genere dovrebbe essere fattibile:

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

Grazie PeyloW la tua risposta era giusta sul posto ... thumbs up ... ti auguro buona fortuna per i tuoi sforzi .... –

+2

Non dovrebbe essere [object objectForKey: @ "name"]; nel lato quel ciclo? –

+0

senza Skeater. Questo è per un NSDictionary. –

1

Se desideri che i tuoi personalizzati sottoclassi NSObject da considerare uguali quando i loro nomi sono uguali si può implementare isEqual: e hash. Ciò consentirà di aggiungere gli oggetti a NSSet/NSMutableSet (un insieme di oggetti distinti).

È quindi possibile creare facilmente un NSArray ordinato utilizzando il metodo sortedArrayUsingDescriptors:NSSet.

MikeAsh ha scritto un pezzo piuttosto solido sull'implementazione di uguaglianza personalizzato: Friday Q&A 2010-06-18: Implementing Equality and Hashing

1

Se siete preoccupati per l'ordine

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

ho intenzione di ottenere critiche per questo ...

Puoi convertire la tua matrice in un dizionario. Non è sicuro quanto sia efficiente, dipende dall'implementazione e dalla chiamata di confronto, ma utilizza una mappa hash.

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

* Nota, questo potrebbe cambiare l'ordine dell'array.

+0

Hehehehe I LOVE this! –

+0

Edit: beh, ho appena passato gli ultimi 15 minuti a correggere un bug nel mio codice. L'utilizzo di questo metodo NSDictionary NON manterrà l'ORDINE del tuo array. Tutti i miei oggetti sono stati strapazzati. Questo è quello che ottengo per l'utilizzo di wordk-around hacky in cui le prefazioni dell'OP "Otterrò critiche per questo ..." lol –

7

So che questa è una vecchia domanda, ma qui c'è un'altra possibilità, a seconda di cosa è necessario.

Apple fornisce un modo per farlo - Key-Value Coding Collection Operators.

Gli operatori oggetto consentono di agire su una raccolta. In questo caso, si vuole:

@distinctUnionOfObjects

L'operatore @distinctUnionOfObjects restituisce un array contenente gli oggetti distinti nella proprietà specificata dal percorso tasto a destra dell'operatore.

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

Nel tuo caso, però, si desidera che l'intero oggetto. Quindi quello che dovresti fare è duplice: 1) Usa invece @distinctUnionOfArrays. Per esempio. Se questi oggetti personalizzati provengono da altre raccolte, utilizzare @distinctUnionOfArray.myCollectionOfObjects 2) Implementare isEqual: su quegli oggetti da restituire se loro.Il nome di sono uguali

0

Implementare IsEqual per rendere i vostri oggetti confrontabili:

@interface SomeObject (Equality) 
@end 

@implementation SomeObject (Equality) 

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

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

@end 

Come usare:

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

è abbastanza semplice in una sola riga

NSArray *duplicateList = ... 

Se non ti interessa l'ordine degli elementi (non ordinato)

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

mantenere gli elementi per poi (ordinato)

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

Ma come è il tuo codice di filtraggio basato sul campo "nome"? – Satyam