Objective c 基于属性从NSArray创建NSSet

Objective c 基于属性从NSArray创建NSSet,objective-c,nsarray,nsset,Objective C,Nsarray,Nsset,如何基于属性从数组创建对象的NSSet e、 g.对象数组,每个对象强烈引用类型属性,数组中存在每种类型的多个引用。如何将其转换为一个包含每种类型的单个对象的NSSet。您可以使用: NSSet* mySetWithUniqueItems= [NSSet setWithArray: yourArray]; 无论阵列中的对象类型如何,此操作都应有效,并且仅使用阵列中出现的一个重复对象填充NSSet 我希望这有帮助 更新: 其次最好的方法是:首先使用类名和对象属性的连接,然后使用上面的方法 sel

如何基于属性从数组创建对象的
NSSet

e、 g.对象数组,每个对象强烈引用
类型
属性,数组中存在每种类型的多个引用。如何将其转换为一个包含每种类型的单个对象的
NSSet

您可以使用:

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输出中获得所需的信息。

字典基本上已经具有此功能。它的键是一个集合,因此您可以创建字典来保存对象,由您感兴趣的任何属性设置键:

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];
    }        
}
[NSDictionary dictionaryWithObjects:arrayOfObjects 
                            forKeys:[arrayOfObjects valueForKey:theAttribute]];
如果现在向词典查询
所有值
,则每个属性只有一个对象。我应该提到的是,在这个过程中,后面的对象将保留在前面的对象中。如果原始数组的顺序很重要,请在创建字典之前将其反转

实际上不能将这些对象放入
NSSet
,因为
NSSet
将使用对象的
isEqual:
hash
方法来确定它们是否应该是成员,而不是键属性(当然,如果这是您自己的类,您可以重写这些方法,但这可能会干扰它们在其他集合中的行为)

如果你真的觉得你需要一个集合,你就必须编写你自己的类。你可以将
NSSet
子类化,但传统的观点是,Cocoa集合的组合要比子类化容易得多。本质上,你编写的类涵盖了你感兴趣的任何集合方法。下面是一个例子(非常不完整且完全未经测试)草图:



我创建了一个简单的库,名为,它是一个方法集合,使此类问题更容易解决。在您的情况下,您需要该方法:


这将返回一个集合,其中每个项都有一个不同的
类型
属性。

是否只需要每个类型的第一个实例?还是任意实例?这实际上不是从数组到集合的明显映射。遍历数组并将这些对象添加到NSMutableSet中。
类型
的类型是什么?它是字符串还是字符串数字,一个对象?我想用一个库方法从相同对象类型的数组中每次出现的属性值中获取一个对象。我自己写了一个来创建集合,但想知道是否有一个优化的库方法。你的问题的简短答案是否。没有“库”方法来做您想做的事情。您已经编写的任何方法都是您需要的。如果您的对象具有相同的
类型
值,并且从
isEqual:
返回
YES
,那么您需要做的就是从数组创建一个集合并完成。但是,由于情况并非如此,您必须编写自己的自定义处理。我希望基于唯一属性值获得一组相同对象类型。@ReyGonzales,我相信这里的复杂性在于,上述方法将使用数组中的唯一对象创建一个NSSet。Hemia希望使用对象级别相似但每个属性不同的对象填充NSSet。是的,例如4 ob数组中的对象,其(NSString*)类型属性设置为@“type1”、“type2”、“type1”、“type3”。将此数组传递到库方法中,以返回包含三个唯一名称的3个对象。因此,与其返回唯一字符串,不如返回包含唯一字符串的对象。我自己编写了此方法,但不知道是否已经在使用优化的库方法。哦,您不需要编写它。也许吧这应该在您的问题中指定。@Helium3,所以您在这里最担心的不是NSSet将包含类实例的副本(因为NSSet在我的回答中自动处理)而是要确保生成的NSSet不包含不同的实例,但具有相同的基础属性?
[NSDictionary dictionaryWithObjects:arrayOfObjects 
                            forKeys:[arrayOfObjects valueForKey:theAttribute]];
@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
NSSet* dictionary = [NSSet setWithArray:[sourceArray distinct:^id(id item) {
    return [item type] ;
}]];