2010-10-24 29 views
11

Mam tablicę z niestandardowymi obiektami. Każdy element tablicy ma pole o nazwie "nazwa". Teraz chcę usunąć zduplikowane wpisy na podstawie tej wartości nazwy.usuwanie duplikatów z tablicy w obiekcie c

Jak mam to osiągnąć?

Z góry dziękuję.

+0

są takie elementy w pojemniku Objective-C jak NSArray lub C/C++ (np std :: wektor lub tablica C)? –

+2

dlaczego tag C? –

+0

sorry usunięto tag, jego cel c tablicy z niestandardowymi obiektami ... "name" jest jedną z jego zmiennych członkowskich, chcę filtrować w oparciu o tę "nazwę" wartości. –

Odpowiedz

9

Można mieć faktycznie napisać tę metodę filtrowania siebie:

@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

to nie jest tablica ciągów jej niestandardowa tablica obiektów .... z nazwą ciągu jako właściwością ... Chcę filtrować oparta na tej nazwie właściwość –

+0

Czy ta ostatnia uwaga będzie komentować? –

+0

@Jacob: Napisałem odpowiedź tak, jak edytowałeś. Naprawdę powinieneś użyć 'NSMutableSet' zamiast' NSMutableArray' dla wyszukiwań, zwiększenie wydajności z hash lookup jest dużo lepsze niż wyszukiwanie liniowe. – PeyloW

27

nie wiem z dowolnym standardowym sposobem do tego dostarczone przez ram zrobić. Będziesz musiał to zrobić w kodzie. Coś takiego powinno być wykonalne:

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

Dzięki PeyloW Twoja odpowiedź była na miejscu ... Kciuk w górę ... Życzę powodzenia w Twoich staraniach .... –

+2

Nie powinien to być [object objectForKey: @ "name"]; w tej pętli? –

+0

bez Skeatera. To dla NSDictionary. –

1

Jeśli chcesz niestandardowych NSObject podklasy należy uznać za równe, gdy ich nazwy są równe można wdrożyć isEqual: i hash. Umożliwi to dodanie obiektów do obiektu NSSet/NSMutableSet (zestawu odrębnych obiektów).

Następnie można łatwo utworzyć posortowane NSArray przy użyciu metody NSSet 's sortedArrayUsingDescriptors:.

MikeAsh napisał całkiem solidny kawałek o wdrożenie niestandardowych równości: Friday Q&A 2010-06-18: Implementing Equality and Hashing

1

Jeśli martwisz się o kolejności

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

Zamierzam dostać flak dla tego ...

Możesz przekonwertować tablicę na słownik. Nie wiem, na ile jest to efektywne, zależy od implementacji i wywołania porównania, ale korzysta z mapy skrótów.

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

* Uwaga, to może zmienić kolejność swojej tablicy.

+0

Hehehehe KOCHAM to! –

+0

Edycja: dobrze spędziłem ostatnie 15 minut naprawiając błąd w moim kodzie. Użycie tej metody NSDictionary NIE zachowuje ORDERU twojej tablicy. Wszystkie moje przedmioty były porozrzucane. To właśnie dostaję za używanie hacky wordk-arounds gdzie OP poprzedza "Mam zamiar dostać flaka za to ..." lol –

7

Wiem, że to stare pytanie, ale tutaj jest inna możliwość, w zależności od potrzeb.

Apple zapewnia sposób na zrobienie tego - Key-Value Coding Collection Operators.

Operatory obiektów umożliwiają działanie w kolekcji. W tym przypadku, chcesz:

@distinctUnionOfObjects

Operator @distinctUnionOfObjects zwraca tablicę zawierającą różne obiekty w nieruchomości określonej przez ścieżkę klucza po prawej stronie operatora.

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

W twoim przypadku jednak, chcesz cały obiekt. To, co musisz zrobić, to podwójnie: 1) Zamiast tego użyj @distinctUnionOfArrays. Na przykład. Jeśli te niestandardowe obiekty pochodzą z innych kolekcji, użyj @distinctUnionOfArray.myCollectionOfObjects 2) Wprowadź isEqual: dla tych obiektów, aby powrócić, jeśli ich.Nazywa się to równa

0

Wdrożenie IsEqual aby Twoje obiekty porównywalne:

@interface SomeObject (Equality) 
@end 

@implementation SomeObject (Equality) 

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

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

@end 

Jak używać:

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

Jest to dość proste w jednej linii

NSArray *duplicateList = ... 

Jeśli nie interesuje cię wtedy porządek elementów (nieuporządkowany)

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

przechowywać elementy w kolejności, a następnie (zamówić)

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

Ale jak filtrowanie twojego kodu bazuje na polu "nazwa"? – Satyam

Powiązane problemy