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
Czy potrzebujesz tylko pierwszej instancji każdego typu? Lub dowolna instancja? To naprawdę nie jest oczywiste odwzorowanie z tablicy do zestawu. –
Powtórz te tablice i dodaj te obiekty do NSMutableSet. – ZhangChn
Jaki jest typ "typu"? Czy to ciąg, liczba, obiekt? – CodaFi