注意:以下SO问题是相关的,但它们和链接资源似乎都没有完全回答我的问题,特别是在实现对象集合的相等性测试方面.
NSObject提供默认实现-hash(返回实例的地址,如(NSUInteger)self)和-isEqual:(NO除非接收者的地址和参数相同,否则返回).这些方法旨在根据需要进行覆盖,但文档清楚地表明您应该同时提供这两种方法,或者两者都不提供.此外,如果-isEqual:返回YES两个对象,那么-hash这些对象的结果必须相同.如果不是这样,当应该相同的对象(例如两个-compare:返回的字符串实例)NSOrderedSame被添加到Cocoa集合或直接比较时,就会出现问题.
我开发了CHDataStructures.framework,这是一个Objective-C数据结构的开源库.我已经实现了许多集合,目前正在改进和增强其功能.我想要添加的功能之一是能够将集合与另一个集合进行比较.
这些比较不应仅比较内存地址,而应考虑两个集合中存在的对象(包括排序,如果适用).这种方法在Cocoa中具有相当先例,并且通常使用单独的方法,包括以下方法:
-[NSArray isEqualToArray:]-[NSDate isEqualToDate:]-[NSDictionary isEqualToDictionary:]-[NSNumber isEqualToNumber:]-[NSSet isEqualToSet:]-[NSString isEqualToString:]-[NSValue isEqualToValue:]我想使我的自定义集合对于相等性测试具有鲁棒性,因此可以安全地(并且可预测地)将它们添加到其他集合中,并允许其他集合(如NSSet)确定两个集合是否相等/等同/重复.
一个-isEqualTo...:方法本身很有用,但是定义这些方法的类通常也会覆盖-isEqual:调用,[self isEqualTo...:]如果参数与接收者属于同一个类(或者可能是子类),或者[super isEqual:]不是.这意味着类还必须定义-hash,以便为具有相同内容的不同实例返回相同的值.
此外,Apple的文档-hash规定如下:(强调我的)
"如果一个可变对象被添加到使用的散列值,以确定该对象的集合中的位置的集合,由对象的哈希方法返回的值不能而所述对象是所述集合中的变化.因此,任一散列法不能依赖于对象的任何内部状态信息,或者必须确保对象在集合中时对象的内部状态信息不会发生变化.因此,例如,可变字典可以放在哈希表中但是你必须当它在那里时不要改变它.(注意,很难知道给定对象是否在集合中.)"
编辑: 我明白为什么这是必要的并完全同意推理 - 我在这里提到它提供额外的背景,并为了简洁而避开了为什么会这样的主题.
我的所有集合都是可变的,并且散列必须至少考虑一些内容,因此这里唯一的选择是将其视为编程错误来改变存储在另一个集合中的集合.(我的集合都采用NSCopying …
经过长时间(20多年)的编程后,我正试图重新开始.我的第一个真正的尝试是Scrabble/Words With Friends求解/骗子(选择你的定义).我已经建立了一个非常好的引擎,但它通过蛮力而不是效率或优雅来解决问题.经过大量研究后,很明显这个问题的最佳答案是DAWG或CDWAG.我已经在那里找到了一些C实现并且能够利用它们(对于相同的数据集,搜索时间从1.5s变为.005s).
但是,我试图弄清楚如何在纯Objective-C中做到这一点.在那,我也试图使其符合ARC标准.并且足够有效的iPhone.我看了很多,发现了几个数据结构库(即CHDataStructures),但它们主要是C/Objective-C混合,或者它们不符合ARC.他们非常依赖结构并将结构嵌入结构中.ARC并不真正关心它.
所以 - 我的问题是(对不起,我明白,如果这是tl;博士,如果它似乎完全是一个新问题 - 只是无法理解这个对象的东西)你如何编程经典数据结构(树等)在Objective-C中从头开始?我不想依赖NS [Mutable] {Array,Set等}.有没有人有一个简单/基本的树实现或类似的东西,我可以创建我的DAWG?
注意:虽然我的特定上下文是Objective-C,但我的问题实际上超越了编程语言的选择.此外,我将其标记为"主观",因为否则有人会抱怨,但我个人认为这几乎完全是客观的.此外,我知道这个相关的SO问题,但由于这是一个更大的问题,我认为最好将这个问题作为一个单独的问题.如果没有完全阅读和理解,请不要批评这个问题.谢谢!
我们大多数人都熟悉存储键值关联的字典抽象数据类型,无论我们将其称为地图,字典,关联数组,哈希等,这取决于我们选择的语言.字典的简单定义可以通过三个属性来概括:
任何其他属性可以说是特定用途的便利或专业化.例如,某些语言(尤其是脚本语言,如PHP和Python)模糊了字典和数组之间的界限,并确实为字典提供了排序.尽管这可能是有用的,但这种添加不是字典的基本特征.纯粹来说,字典的实际实现细节是无关紧要的.
对于我的问题,最重要的观察是枚举键的顺序没有定义 - 字典可以按照它最方便的顺序提供键,并且由客户端根据需要组织它们.
我创建了自定义词典,它们强加了特定的键排序,包括自然排序顺序(基于对象比较)和插入顺序.很明显,在SortedDictionary(我实际上已经实现过)中给前者命名了一些变体,但后者更成问题.我见过LinkedHashMap和LinkedMap(Java),OrderedDictionary(.NET),OrderedDictionary(Flash),OrderedDict(Python)和OrderedDictionary(Objective-C).其中一些更成熟,一些更符合概念.
LinkedHashMap是根据Java集合传统中的实现命名的 - "链接"因为它使用双向链表来跟踪插入顺序,而"哈希"因为它是HashMap的子类.除了用户不需要担心的事实之外,类名甚至不能指出它的作用.使用有序似乎是现有代码之间的共识,但是关于这个主题的网络搜索也揭示了"有序"和"有序"之间可理解的混淆,我感觉是一样的..NET实现甚至有一个关于明显误称的评论,并建议它应该是"IndexedDictionary",因为您可以在排序中的特定点检索和插入对象.
我正在设计一个框架和API,我希望尽可能智能地命名该类.从我的观点来看,索引可能会起作用(取决于人们如何解释它,并基于字典的广告功能),有序是不精确的,并且有太多混淆的可能性,并且链接 "是正确的"(对Monty Python道歉) ).;-)
作为用户,您最有意义的名称是什么?是否有一个特定的名称,确切地说明了该课程的作用?(如果合适的话,我不反对使用稍长的名字,比如InsertionOrderDictionary.)
编辑:另一个强大的可能性(在我的答案中讨论)是IndexedDictionary.我真的不喜欢"插入顺序",因为如果允许用户在特定索引处插入键,重新排序键等,则没有意义.
api-design objective-c naming-conventions chdatastructures data-structures
对于我的游戏iOS项目,我需要一个环形缓冲区.它应该类似于一个队列,其中元素输出并进入,但缓冲区中元素的总量应保持不变.
我使用java成功实现了环形缓冲区,但我不熟悉objective-c.我在网上找到了一个名为CHCircularBuffer的环形缓冲区实现:https://bitbucket.org/devartum/chdatastructures/src/4d6d7194ee94/source/CHCircularBuffer.m 但是我没能正确实现它.
循环缓冲区是名为TerrainManager的类的属性,它可以生成所有数学地形.
@interface TerrainManager : NSObject{
int terrainParts;
CHCircularBuffer* circularTerrainBuffer;
}
@property(nonatomic, retain) CHCircularBuffer *circularTerrainBuffer;
@end
Run Code Online (Sandbox Code Playgroud)
这是如何在TerrainManager的实现中初始化环形缓冲区
circularTerrainBuffer = [[CHCircularBuffer alloc] initWithCapacity:parts];
Run Code Online (Sandbox Code Playgroud)
这将创建缓冲区的实例,并将size属性设置为parts.现在我使用addObject方法将对象添加到缓冲区:
[circularTerrainBuffer addObject:[NSNumber numberWithDouble:0.2]];
Run Code Online (Sandbox Code Playgroud)
有时这行会收到错误"exec_bad_access".例如,当我初始化容量为15的缓冲区时,一切都很好,20我得到了错误.
我现在尝试从绘图发生的terrain类访问缓冲区.但每当我尝试访问对象时,我都会收到"bad_access"错误.
NSArray *arr = [terrainManager.circularTerrainBuffer allObjects];
Run Code Online (Sandbox Code Playgroud)
例如,这一行会产生错误.
所以我的代码有问题.也许我不理解缓冲区并以错误的方式添加对象.我不知道.任何想法或建议?
为了帮助简化Xcode调试器窗口中某些自定义Objective-C对象的调试,我使用相关的Apple文档和Xcode的内置数据格式化程序作为指南,为每个对象创建了一组数据格式化程序字符串.
如果我将自定义摘要字符串放在/ Developer/Library/Xcode/CustomDataViews /中,并附带Xcode附带的数据格式化程序,那么我的自定义摘要字符串效果很好.但是,我宁愿不这样做,因为用户可能没有该目录的写权限,并且将自定义格式化程序与内置格式化程序混合可能会造成混淆.类似地,将我自己的条目添加到〜/ Library/Application Support/Apple/Developer Tools/CustomDataViews/CustomDataViews.plist也可以,但该文件用于覆盖默认值的用户定义值,并且其条目受到更改的影响. Xcode调试器GUI.我真正想要的是能够将我的数据格式化程序放在一个位置,以便Xcode识别它们,但如果需要,用户仍然可以有选择地覆盖我的设置(在另一个文件中).
问题是,当我创建一个包(按照这个Apple示例代码的示例)并安装它时(在/ Developer/Library/Xcode/CustomDataViews /或任何库/应用程序支持/ Apple/Developer Tools/CustomDataViews / path中) ,Xcode无法识别或使用自定义格式化程序.
有关数据格式化程序包特定内容的文档有点不足(主要是Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin中的单个头文件),可能是因为该功能不是Xcode的标题功能之一.;-) 任何帮助将不胜感激.