2013-03-07 17 views
8

Jak utworzyć obiekt z tablicy na podstawie właściwości.Utwórz NSSet z NSArray na podstawie właściwości

np. Tablica obiektów, z których każda ma silne odniesienie do właściwości i wiele wystąpień każdego typu, istnieje w tablicy. W jaki sposób można przekształcić go w obiekt o jednym obiekcie każdego typu.

+0

Czy potrzebujesz tylko pierwszej instancji każdego typu? Lub dowolna instancja? To naprawdę nie jest oczywiste odwzorowanie z tablicy do zestawu. –

+0

Powtórz te tablice i dodaj te obiekty do NSMutableSet. – ZhangChn

+0

Jaki jest typ "typu"? Czy to ciąg, liczba, obiekt? – CodaFi

Odpowiedz

0

użyłbyś:

NSSet* mySetWithUniqueItems= [NSSet setWithArray: yourArray]; 

ten powinien działać niezależnie od rodzaju obiektów w tablicy i byłoby zapełnić NSSet tylko z jednym wystąpieniem jakichkolwiek duplikatów obiektów w tablicy.

Mam nadzieję, że to pomoże.

Aktualizacja: Następną najlepszą rzeczą jest zastosowanie konkatenacji nazwy klasy i właściwości obiektu, a następnie użycie powyższej metody.

self.concatenatedArray=[NSMutableArray arrayWithCapacity:4]; 

for (TheClass* object in self.myArray) 
    [self.concatenatedArray addObject:[NSString stringWithFormat:@"%@-%@",[object class], object.theProperty]]; 

self.mySet=[NSSet setWithArray:self.concatenatedArray]; 

Nie jestem pewien, co można wykorzystać wyjście NSSet dla ale prawdopodobnie można modyfikować elementy konkatenacji mieć potrzebne informacje na wyjściu NSSet.

+0

Chciałbym uzyskać zestaw tego samego typu obiektu na podstawie unikalnych wartości właściwości. – jarryd

+0

Co to znaczy? –

+0

@ReyGonzales, Wierzę, że złożoność jest taka, że ​​powyższa metoda stworzy NSSet z unikalnymi obiektami z tablicy. Hel szuka możliwości zapełnienia NSSet obiektami, które są podobne na poziomie obiektu, ale mają inną właściwość. – Spectravideo328

0
NSMutableSet* classes = [[NSMutableSet alloc] init]; 
NSMutableSet* actualSet = [[NSMutableSet alloc] init]; 

for(id object in array) { 
    if([classes containsObject:[object class]] == NO) { 
     [classes addObject:[object class]]; 
     [actualSet addObject:object]; 
    }   
} 
7
NSSet *distinctSet = [NSSet setWithArray:[array valueForKeyPath:@"@distinctUnionOfObjects.property"]]; 
2

Słownik zasadniczo ma już tej funkcji. Jej klawisze są zbiorem, dzięki czemu można tworzyć słownika do przechowywania przedmiotów, wpisanych przez cokolwiek atrybut jesteś zainteresowany:

[NSDictionary dictionaryWithObjects:arrayOfObjects 
          forKeys:[arrayOfObjects valueForKey:theAttribute]]; 

Jeśli zapytać słownika dla allValues teraz, masz tylko jeden obiekt dla każdego atrybut. Powinienem wspomnieć, że dzięki tej procedurze, późniejsze obiekty zostaną zachowane na korzyść wcześniejszych. Jeśli kolejność oryginalnej tablicy jest znacząca, odwróć ją przed utworzeniem słownika.

Nie można faktycznie umieścić te obiekty w produkt NSSet, ponieważ NSSet użyje isEqual: i hash metody obiektów, aby określić, czy powinny one być członkami zamiast atrybutu kluczowego (oczywiście można zastąpić te metody jeśli jest to twoja własna klasa, ale to prawdopodobnie wpłynęłoby na ich zachowanie w innych kolekcjach).

Jeśli naprawdę czujesz, że potrzebujesz zestawu, musisz napisać własną klasę. Możesz podklasę NSSet, ale konwencjonalna mądrość jest taka, że ​​kompozycja kolekcji Cocoa jest znacznie łatwiejsza niż podklasy. Zasadniczo, można napisać klasę, która obejmuje każdy zestaw metod, które Cię interesują Oto (dość niekompletne i całkowicie niesprawdzone) szkic.

@interface KeyedMutableSet : NSObject 

/* This selector is performed on any object which is added to the set. 
* If the result already exists, then the object is not added. 
*/ 
@property (assign, nonatomic) SEL keySEL; 

- (id)initWithKeySEL:(SEL)keySEL; 

- (id)initWithArray:(NSArray *)initArray usingKeySEL:(SEL)keySEL; 

- (void)addObject:(id)obj; 

- (NSArray *)allObjects; 

- (NSArray *)allKeys; 

- (BOOL)containsObject:(id)obj; 

- (NSUInteger)count; 

-(void)enumerateObjectsUsingBlock:(void (^)(id, BOOL *))block; 

// And so on... 

@end 

#import "KeyedMutableSet.h" 

@implementation KeyedMutableSet 
{ 
    NSMutableArray * _objects; 
    NSMutableSet * _keys; 
} 

- (id)initWithKeySEL:(SEL)keySEL 
{ 
    return [self initWithArray:nil usingKeySEL:keySEL]; 
} 

- (id)initWithArray:(NSArray *)initArray usingKeySEL:(SEL)keySEL 
{ 
    self = [super init]; 
    if(!self) return nil; 

    _keySEL = keySEL; 
    _objects = [NSMutableArray array]; 
    _keys = [NSMutableSet set]; 

    for(id obj in initArray){ 
     [self addObject:obj]; 
    } 

    return self; 
} 

- (void)addObject:(id)obj 
{ 
    id objKey = [obj performSelector:[self keySEL]]; 
    if(![keys containsObject:objKey]){ 

     [_keys addObject:objKey]; 
     [_objects addObject:obj]; 
    } 
} 

- (NSArray *)allObjects 
{ 
    return _objects; 
} 

- (NSArray *)allKeys 
{ 
    return [_keys allObjects]; 
} 

- (BOOL)containsObject:(id)obj 
{ 
    return [_keys containsObject:[obj performSelector:[self keySEL]]]; 
} 

- (NSUInteger)count 
{ 
    return [_objects count]; 
} 

- (NSString *)description 
{ 
    return [_objects description]; 
} 

-(void)enumerateObjectsUsingBlock:(void (^)(id, BOOL *))block 
{ 
    for(id obj in _objects){ 
     BOOL stop = NO; 
     block(obj, &stop); 
     if(stop) break; 
    } 
} 

@end 
0

Stworzyłem prostą bibliotekę, zwany Linq to ObjectiveC , który jest zbiorem metod, dzięki którym tego rodzaju problem jest łatwiejszy do rozwiązania. W twoim przypadku trzeba metodę Linq-to-ObjectiveC distinct:

NSSet* dictionary = [NSSet setWithArray:[sourceArray distinct:^id(id item) { 
    return [item type] ; 
}]]; 

Zwraca zestaw, w którym każdy element ma wyraźną type nieruchomości.

Powiązane problemy