2013-03-07 12 views
8

Come si crea uno NSSet di oggetti da un array in base a una proprietà.Creazione di un NSSet da NSArray in base alla proprietà

ad es. La matrice di oggetti, ciascuno con un forte riferimento a una proprietà type e più occorrenze di ogni tipo, esiste nell'array. Come può essere trasformato in un NSSet con un singolo oggetto di ogni tipo.

+0

Vuoi solo la prima istanza di ogni tipo? O un'istanza arbitraria? Questa non è una mappatura evidente da un array a un set. –

+0

Iterate attraverso l'array e aggiungete tali oggetti in un NSMutableSet. – ZhangChn

+0

Qual è il tipo di 'tipo'? È una stringa, un numero, un oggetto? – CodaFi

risposta

0

si userebbe:

NSSet* mySetWithUniqueItems= [NSSet setWithArray: yourArray]; 

Questo dovrebbe funzionare indipendentemente dal tipo di oggetti in vostro matrice e avrebbero popolato la NSSet con un solo verificarsi di eventuali oggetti duplicati nel vostro array.

Spero che questo aiuti.

Aggiornamento: La cosa migliore: usare concatenazione del nome della classe e della proprietà dell'oggetto, quindi utilizzare il metodo precedente.

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]; 

io non sono sicuro di quello che si intende utilizzare l'uscita NSSet per ma probabilmente è possibile modificare gli elementi concatenazione di avere le informazioni necessarie nell'output NSSet.

+0

Vorrei ottenere un set dello stesso tipo di oggetto basato su valori di proprietà univoci. – jarryd

+0

Che cosa significa? –

+0

@ReyGonzales, credo che la complessità qui sia che il metodo precedente creerebbe un NSSet con oggetti unici dall'array. L'elio sta cercando di popolare l'NSSet con oggetti simili a livello di oggetto ma ciascuno con una proprietà diversa. – 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

Un dizionario ha essenzialmente questa funzionalità già. I tasti sono un insieme, in modo da poter creare il dizionario per contenere gli oggetti, calettati con qualsiasi attributo che ti interessa:

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

Se chiedete il dizionario per allValues ora, si dispone di un solo oggetto per ogni attributo. Dovrei menzionare che con questa procedura, gli oggetti successivi saranno mantenuti in favore di prima. Se l'ordine dell'array originale è significativo, invertirlo prima di creare il dizionario.

non si può effettivamente mettere quegli oggetti in un NSSet, perché il NSSet userà degli oggetti isEqual: e hash metodi per determinare se debbano essere membri, piuttosto che l'attributo chiave (naturalmente, è possibile ignorare questi metodi se questa è la tua classe, ma probabilmente interferirebbe con il loro comportamento in altre raccolte).

Se davvero senti che hai bisogno di un set, dovrai scrivere la tua classe. È possibile creare una sottoclasse di NSSet, ma la saggezza convenzionale è che la composizione delle raccolte di Cocoa è molto più semplice rispetto alla sottoclasse. In sostanza, si scrive una classe che copre tutti i metodi set che ti interessa Ecco un (abbastanza incompleta e totalmente non testato) schizzo:.

@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

Ho creato una semplice libreria, chiamata Linq to ObjectiveC , che è una raccolta di metodi che rende questo tipo di problema molto più facile da risolvere. Nel tuo caso è necessario il metodo Linq-to-ObjectiveC distinct:

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

Questo restituisce un set in cui ogni elemento ha una distinta type proprietà.

Problemi correlati