NSSet -member检查NSValue的相等性
我有一个包含数千个NSValue
对象的NSSet
(包装CGPoints
)。 我想很快找到NSSet
是否存在给定的CGPoint
值。 在我看来, NSSet
的member:
方法可以在这里完成工作,除了它使用isEqual:
检查相等性。 NSValue
对象使用isEqualToValue:
,因此当我执行代码时:
[mySet member:valueToCheck];
它实际上导致Xcode崩溃。
1)是否有某种方法可以使用自定义相等性检查来使其适用于NSValue
对象?
2)这是否是最好的方法(即member:
首先是否足够快)? 场景是我有一个NSSet
包含大量代表屏幕(iPad)像素的点。 后来我需要以每秒数千点的速度轰击那一组,看看它们是否存在于集合中。 我的方法似乎很难实现这一点。 我想创建类似于一个巨大的二维位数组的东西,每个索引代表一个屏幕上的像素。 一旦我知道了我正在测试的那一点,我就可以直接跳到arrays中的那一点并检查1或0 ……这听起来好不好?
谢谢
你能把它变成一个简单的可重复的案例吗? 例如,我刚试过:
NSValue *v = [NSValue valueWithCGPoint:CGPointMake(1, 1)]; NSSet *s = [NSSet setWithObject:v]; NSLog(@"%@", [s member:[NSValue valueWithCGPoint:CGPointMake(1, 1)]]);
但它的工作正常。
编辑
-isEqual:
不是问题:
NSValue *v1 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSValue *v2 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSLog(@"%d", [v1 isEqual:v2]); //logs "1"
-hash
不是问题:
NSLog(@"%d", ([v1 hash] == [v2 hash])); //logs "1"
它们是不同的对象:
NSLog(@"%d", (v1 != v2)); //logs "1"
问题出在您的代码中。 尝试清洁和重建。
回答否。 2:
我不知道NSSet是如何在内部实现的,但考虑到你知道你在存储点(使用X和Y),我认为通过实现自己的分区算法会更好。 我个人会选择我自己的实现而不是NSSet,如果你说你有数千点。
为每个像素存储巨大的二维数组可能是最快的方法,但它会在内存消耗方面杀死你。 你需要快速的东西,但也要轻巧。
有很多算法,您可以通过在维基百科或谷歌上搜索“空间分区算法”找到它们。 这还取决于您的编程技巧,以及您愿意投入多少时间。
例如,一个非常简单的方法是实现四叉树,在这里您可以将屏幕(或区域)分成4个相等的部分。 然后,如果需要,可以将该特定单元划分为4个部分。 并且这样做直到每个单元格包含足够少的点数,以便您可以对所有单元格进行暴力测试。 你可以在wiki上找到一个非常好的描述: http : //en.wikipedia.org/wiki/Quadtree
希望这可以帮助,
[mySet member:valueToCheck]
不应该崩溃。 NSValue的isEqual:
当我在这里尝试时工作正常,实际上可能调用isEqualToValue:
当给出另一个NSValue进行比较时。 valueToCheck
真的是NSValue,还是CGPoint?
无法覆盖NSSet的默认哈希和比较方法。 但是NSSet与CFSetRef
是免费的桥接,您可以在那里轻松指定自定义哈希和比较方法:
CFSetCallBacks callbacks = kCFTypeSetCallBacks; callbacks.equal = customEqualFunction; callbacks.hash = customHashFunction; NSMutableSet *set = (NSMutableSet *)CFSetCreateMutable(NULL, 0, &callbacks);
对这些函数的约束大概与NSObject的hash
和isEqual:
方法相同,任何相同的东西必须具有相同的散列。 这里和这里描述了customEqualFunction
和customHashFunction
的C风格原型。
一种解决方案是子类化NSSet
并覆盖member:
进行自己的比较。 然后你自己的比较可以简单地调用isEqualToValue:
. 查看NSSet
文档中的子类注释。
另一种方法是向实现isEqual:
NSValue
添加一个类别isEqual:
。 在这种情况下,我更喜欢子类化,因为它是一个更有限的解决方案。
这不仅仅是-isEqual:
一个问题-isEqual:
你也可能遇到-hash方法的问题。 如果要使用NSSet,则应该创建一个包装CGPoint的自定义类。 -isEqual:
然后是微不足道的, -hash
可以通过组合两个坐标的位然后将它们作为NSUInteger处理的某种方法来实现。
您还需要实现NSCopying
协议,如果您的点是不可变的,那么这也是微不足道的(只需保留并返回self in -copyWithZone:
。