2

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

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

现在,对于问题的关键,我想做的是检查有多少独特的点。我打算用一个NSMutableSet来做。IE:

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

4 回答 4

7

NSSetisEqual在测试成员资格时使用。
isEqual:并且hashNSObject 协议的一部分。

如果您的 XYPoint 类从 NSObject 派生,它会继承默认的 isEqual: 基于指针相等的实现。它比较内存地址以测试 2 个对象是否相同。
由于您的比较标准是location,因此您必须isEqual:在 XYPoint 类中覆盖并返回YES,如果您的 2 个对象的 x/y 坐标相同。

另请查看集合编程主题Mike Ash还有一篇关于平等和散列的非常详细的帖子。

更新
正如 JeremyP 在评论中指出的那样,您应该始终提供 when overriding 的hash实现isEqual:。详细信息在上面的 Mike Ash 文章中进行了解释。
还有一个问题在 Stack Overflow 上讨论坐标的良好哈希函数。

于 2013-04-23T06:35:54.437 回答
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]];
}
于 2013-04-23T08:24:30.610 回答
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
于 2013-04-23T09:34:48.337 回答
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 ,情况并非如此。只是一个快速的解决方案。

于 2013-04-23T08:09:05.173 回答