2013-03-07 4 views
8

Как создать объект NSSet объектов из массива на основе свойства.Создайте NSSet из NSArray на основе свойства

например. Массив объектов, каждый из которых имеет сильную ссылку на свойство type, и в массиве существует множество вхождений каждого типа. Как это можно превратить в NSSet, где находится один объект каждого типа.

+0

Вам нужен только первый экземпляр каждого типа? Или произвольный экземпляр? На самом деле это не очевидное отображение из массива в набор. –

+0

Перейдите через массив и добавьте эти объекты в NSMutableSet. – ZhangChn

+0

Каков тип 'type'? Это строка, число, объект? – CodaFi

ответ

0

Вы могли бы использовать:

NSSet* mySetWithUniqueItems= [NSSet setWithArray: yourArray]; 

Это должно работать независимо от типа объектов в массиве и будет заполнять NSSet только один вхождение дублирующихся объектов в массиве.

Надеюсь, это поможет.

Обновление: Следующая лучшая вещь: сначала используется конкатенация имени класса и свойства объекта, затем используйте вышеуказанный метод.

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

Я не уверен, что вы будете использовать выход NSSet для но вы, вероятно, можете изменить элементы конкатенации, чтобы иметь необходимую информацию в выходной NSSet.

+0

Я хотел бы получить набор одного и того же типа объекта, основанный на уникальных значениях свойств. – jarryd

+0

Что это значит? –

+0

@ReyGonzales, я считаю, что сложность здесь заключается в том, что вышеупомянутый метод создал NSSet с уникальными объектами из массива. Гелий надеется заполнить NSSet объектами, которые похожи на уровне объекта, но имеют разные свойства. – 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

Словарь по существу имеет такую ​​функциональность уже. Его клавиши представляют собой набор, так что вы можете создать словарь для хранения объектов, в привязке любого атрибута вы заинтересованы в:

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

Если вы спросите словарь для allValues сейчас, у вас есть только один объект для каждого атрибут. Я должен упомянуть, что с этой процедурой более поздние объекты будут сохранены в пользу ранее. Если порядок исходного массива значителен, отмените его перед созданием словаря.

Вы не можете фактически поместить эти объекты в NSSet, потому что NSSet будет использовать isEqual: и hash методы Объектами, чтобы определить, должны ли они быть членами, а не ключевого атрибута (конечно, вы можете заместить эти методы если это ваш собственный класс, но это, вероятно, будет мешать их поведению в других коллекциях).

Если вы действительно чувствуете, что вам нужен набор, вам придется написать свой собственный класс. Вы можете подкласса NSSet, но общепринятая мудрость заключается в том, что состав коллекций какао намного проще, чем подклассы. По сути, вы пишете класс, который охватывает любые методы, заданные вам интересны Вот (весьма неполно и совершенно непроверенные) эскиз:.

@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

Я создал простую библиотеку, называется Linq to ObjectiveC , который представляет собой набор методов, облегчающих решение такого рода задач. В вашем случае вам нужен Linq-to-ObjectiveC distinct метод:

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

Это возвращает набор, где каждый элемент имеет отчетливую type свойства.

Смежные вопросы