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

Objective c 检查可变集是否包含具有相同属性的对象,objective-c,Objective C,我想做的是创建一个NSMutableSet,其目的是计算有多少对唯一数据 基本上,我有两个可变数组xCoordinates和yccoordinates,以及名为XYPoint的自定义对象。在重合索引处的每个X坐标和Y坐标组合在笛卡尔平面上形成一个点。例如,在索引2处,在xCoordinates数组中可能有数字4,在yccoordinates数组中可能有数字8,表示点(4,8) 现在,对于问题的关键,我想做的是检查有多少独特点。我计划使用一个NSMutableSet来完成它。即: for (int

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

基本上,我有两个可变数组
xCoordinates
yccoordinates
,以及名为
XYPoint
的自定义对象。在重合索引处的每个X坐标和Y坐标组合在笛卡尔平面上形成一个点。例如,在索引2处,在
xCoordinates
数组中可能有数字4,在
yccoordinates
数组中可能有数字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];

        }

    }

NSSet
在测试成员资格时使用
isEqual

isEqual:
散列

如果XYPoint类派生自NSObject,它将继承基于指针相等的默认isEqual:实现。它比较内存地址以测试两个对象是否相同。
由于比较标准是位置,如果两个对象的x/y坐标相同,则必须在XYPoint类中重写
isEqual:
,并返回
YES

还可以看一看。 还有一个非常详细的帖子

更新
正如JeremyP在评论中指出的,在重写
isEqual:
时,您应该始终提供
hash
的实现。有关详细信息,请参见上面的Mike Ash文章。

还有一个问题是讨论坐标的好的散列函数。

在我的脑海中,可能一些产生唯一结果的操作对于您的特定情况就足够了(尽管可能不是最有效的解决方案)

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];//已编辑
if(![distinct containsObject:coordStr]){
[distinct addObject:coordStr];
}
}

我想应该是这样。您的解决方案不起作用,因为每次都会创建一个新对象,并且不相等。但对于上面的NSString,情况并非如此。只是一个快速的解决方案。

这里是拉凯什提案的增强版

它不受数字到字符串转换的微妙影响,而且它省略了冗余的条件

它使用通用的
NSValue
点包装器,而不是自定义类
XYPoint

for (NSUInteger i = 0; i < [xCoordinates count]; ++i) {
    CGPoint p = { [xCoordinates[i] floatValue], [yCoordinates[i] floatValue] };
   [distinct addObject:[NSValue valueWithCGPoint:p]];
}
for(整数i=0;i<[xCoordinates count];+i){
CGP点={[xCoordinates[i]floatValue],[yCoordinates[i]floatValue]};
[distinct addObject:[NSValue valueWithCGPoint:p]];
}
在这里扩展哪一个是最好的,类实现看起来像这样:

@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

我猜set只允许唯一的值,它不会在其中添加重复的值。有关详细信息,请检查此问题/答案:+1以获得详细解释和Mike Ash链接。这比将坐标转换为字符串要好得多。但是您还需要重写
-hash
,以便两个相等的对象具有相同的hash。好的,谢谢。我更新了我的答案,有一个隐藏的错误。提示:考虑要点:1, 11和11, 1。我没想到。已更新(在%@s之间添加了一个空格)。只是一个注释<代码>值WithCgPoint:仅在iOS中可用。cocoa中有类似的东西吗?顺便说一句,这不检查唯一性。@Rakesh OS X具有
值WithPoint:
。这里描述了将CGPoints放入NSValue的一般方法:@Rakesh我认为很明显,
distinct
是一个
NSMutableSet
(考虑唯一性)。这就是为什么我称之为条件冗余。是的。但是,当以这种方式创建CG点时,对象之间的相等性并不满足,具有相同坐标的点被添加到
distinct
集合中。所以OP的问题仍然存在。
for (NSUInteger i = 0; i < [xCoordinates count]; ++i) {
    CGPoint p = { [xCoordinates[i] floatValue], [yCoordinates[i] floatValue] };
   [distinct addObject:[NSValue valueWithCGPoint:p]];
}
@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