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