检查可变集是否包含具有相同属性的对象

时间:2013-04-23 06:12:39

标签: objective-c

我想要做的是创建一个NSMutableSet,其目的是计算有多少对唯一数据。

基本上,我有两个可变数组; xCoordinatesyCoordinates以及名为XYPoint的自定义对象。重合索引处的每个X坐标和Y坐标组合在笛卡尔平面上形成一个点。例如,在索引2处,可能在xCoordinates数组中,数字4和yCoordinates数组中的数字8,即点(4,8)。

现在,问题的关键,我想要做的是检查有多少唯一的点。我打算用NSMutableSet来做。即:

for (int i = 0; i < [xCoordinates count]; i++) {

        XYPoint *newXY = [[XYPoint alloc] init];
        newXY.xCoordinate = [xCoordinates objectAtIndex:i];
        newXY.yCoordinate = [yCoordinates objectAtIndex:i];

        if ([distinct containsObject:newXY] == NO) {

            [distinct addObject:newXY];

        }

    }

不幸的是,这不起作用。有没有办法说出来;

if (there isn't an object in the set with an identical X coordinate property and Y coordinate property){

    Add one to the set;

}

4 个答案:

答案 0 :(得分:7)

在测试会员资格时,

NSSet会使用isEqual isEqual:hashNSObject protocol的一部分。

如果你的XYPoint类派生自NSObject,它继承了基于指针相等性的默认isEqual:implementation。它比较内存地址以测试2个对象是否相同 由于您的比较标准是 location ,您必须覆盖XYPoint类中的isEqual:,如果两个对象的x / y坐标相同,则返回YES

另请查看Collections Programming Topics。 还有一篇关于equality and hashing by Mike Ash的非常详细的帖子。

<强>更新
正如JeremyP在评论中指出的那样,在覆盖hash时,您应始终提供isEqual:的实施。细节在上面的Mike Ash文章中有解释 还有一个问题讨论坐标here on Stack Overflow的良好散列函数。

答案 1 :(得分:2)

以下是Rakesh提案的增强版。

它没有遭受数字到字符串转换的微妙之处,而且它省略了冗余条件。

它使用常见的NSValue点包装器而不是您的自定义类XYPoint

for (NSUInteger i = 0; i < [xCoordinates count]; ++i) {
    CGPoint p = { [xCoordinates[i] floatValue], [yCoordinates[i] floatValue] };
   [distinct addObject:[NSValue valueWithCGPoint:p]];
}

答案 2 :(得分:2)

扩展weichsel's answer这里最好的,类实现看起来像这样:

@interface XYCoordinate : NSObject
-(id) initWithX: (NSNumber*) newX andY: (NSNumber*) newY;
@property (readonly, copy) NSNumber* x;
@property (readonly, copy) NDNumber* y;
@end

@implementation XYCoordinate

@synthesize x = _x;
@synthesize y = _y;

-(id) initWithX: (NSNumber*) newX andY: (NSNumber*) newY
{
    self = [super init];
    if (self != nil)
    {
         [self setX: newX];
         [self setY: newY];
    }
    return self;
}

-(BOOL) isEqual: (id) somethingElse
{
    BOOL ret = NO;
    if ([somethingElse isKindOfClass: [XYCoordinate class]])
    {
        ret = [[self x] isEqual: [somethingElse x]] && [[self y] isEqual: [somethingElse y]]
    }
    return ret;
}

-(NSUInteger) hash
{
     return [[self x] hash] + [[self y] hash];  // Probably a rubbish hash function, but it will do
}
@end

答案 3 :(得分:0)

从头到尾可能会产生一个独特结果的操作对于你的特定情况就足够了(虽然可能不是最有效的解决方案)。

for (int i = 0; i < [xCoordinates count]; i++) {

    NSString *xStr = [[xCoordinates objectAtIndex:i] stringValue];
    NSString *yStr = [[yCoordinates objectAtIndex:i] stringValue];
    NSString *coordStr = [NSString stringWithFormat:@"%@ %@",xStr,yStr]; //edited
    if (![distinct containsObject:coordStr]) {
       [distinct addObject:coordStr];
    }
}

我猜应该这样做。您的解决方案无法正常工作,因为每次创建一个新对象并且不相等。但对于像上面的NSString而言并非如此。只是一个快速的解决方案。