命名以可预测的顺序存储密钥的字典结构?

时间:2009-06-20 19:06:43

标签: objective-c data-structures naming-conventions api-design chdatastructures

  

注意:虽然我的特定上下文是Objective-C,但我的问题实际上超越了编程语言的选择。此外,我将其标记为“主观”,因为否则有人会抱怨,但我个人认为这几乎完全是客观的。另外,我知道this related SO question,但由于这是一个更大的问题,我认为最好将其作为一个单独的问题。如果没有完全阅读和理解,请不要批评这个问题。谢谢!

我们大多数人都熟悉存储键值关联的dictionary abstract data type,无论我们将其称为地图,字典,关联数组,哈希等,这取决于我们选择的语言。字典的简单定义可以通过三个属性来概括:

  1. 按键访问值(而不是索引,如数组)。
  2. 每个键都与一个值相关联。
  3. 每个密钥必须是唯一的。
  4. 任何其他属性可以说是特定用途的便利或专业化。例如,某些语言(尤其是脚本语言,如PHP和Python)模糊了字典和数组之间的界限,并确实为字典提供了排序。尽管这可能是有用的,但这种添加不是字典的基本特征。纯粹来说,字典的实际实现细节是无关紧要的。

    对于我的问题,最重要的观察是枚举键的顺序未定义 - 字典可以按照它找到的最方便的顺序提供键,它取决于客户根据需要组织它们。

    created custom dictionaries强制执行特定的键排序,包括自然排序顺序(基于对象比较)和插入顺序。很明显,将前者命名为 SortedDictionary (我实际上已经实现过),但后者更有问题。我见过LinkedHashMapLinkedMap(Java),OrderedDictionary(.NET),OrderedDictionary(Flash),OrderedDict(Python)和{{ 3}}(Objective-C)。其中一些更成熟,一些更符合概念。

    LinkedHashMap 是根据Java集合传统中的实现命名的 - “链接”,因为它使用双向链表来跟踪插入顺序,而“哈希”因为它是HashMap的子类。除了用户不需要担心的事实之外,类名甚至不能指出它的作用。使用有序似乎是现有代码之间的共识,但是对此主题的网络搜索也揭示了“有序”和“有序”之间可理解的混淆,我也有同感。 .NET实现甚至有一个关于明显用词不当的评论,并建议它应该是“IndexedDictionary”,因为你可以在排序的特定点检索和插入对象。

    我正在设计一个框架和API,我希望尽可能智能地命名该类。从我的角度来看,索引可能会起作用(取决于人们如何解释它,并根据字典的广告功能),有序是不精确的,并且具有太大的潜力混乱,链接“正好”(对Monty Python道歉)。 ; - )

    作为用户,您最感兴趣的名称是什么?是否有一个特定的名称,确切地说明了该课程的作用? (如果合适的话,我不反对使用稍长的名字,比如InsertionOrderDictionary。)

    编辑:另一个强大的可能性(在下面我的回答中讨论)是 IndexedDictionary 。我不太喜欢“插入顺序”,因为如果允许用户在特定索引处插入键,重新排序键等,则没有意义。

9 个答案:

答案 0 :(得分:6)

我投票给OrderedDictionary,原因如下:

除了一个实例外,

“Indexed”从未在Cocoa类中使用过。它总是显示为名词(NSIndexSet,NSIndexPath,objectAtIndex:等)。 “Index”作为动词出现时只有一个实例,它位于NSPropertyDescription的“索引”属性上:isIndexed和setIndexed。 NSPropertyDescription大致类似于数据库中的表列,其中“索引”是指优化以加快搜索时间。因此,如果NSPropertyDescription是Core Data框架的一部分,那么“isIndexed”和“setIndexed”将等同于SQL数据库中的索引。因此,将其称为“IndexedDictionary”似乎是多余的,因为创建数据库中的索引以加快查找时间,但字典已经具有O(1)查找时间。然而,称它为“IndexDictionary”也是一个用词不当,因为Cocoa中的“索引”指的是位置,而不是订单。这两者在语义上是不同的。

我理解你对“OrderedDictionary”的关注,但先例已经在Cocoa中设置了。当用户想要维护特定的序列时,他们使用“有序”: - [NSApplication orderedDocuments], - [NSWindow orderedIndex], - [NSApplication orderedWindows]等等。所以,John Pirie大多是正确的想法。

但是,您不希望在字典中插入对用户造成负担。他们想要创建一个字典一次,然后让它保持适当的顺序。他们甚至不想按特定顺序请求对象。订单规范应在初始化期间完成。

因此,我建议使OrderedDictonary成为一个类集群,具有InsertionOrderDictionary和NaturalOrderDictionary以及CustomOrderDictionary的私有子类。然后,用户只需创建一个OrderedDictionary,如下所示:

OrderedDictionary * dict = [[OrderedDictionary alloc] initWithOrder:kInsertionOrder];
//or kNaturalOrder, etc

对于CustomOrderDictionary,您可以让它们为您提供比较选择器,甚至(如果它们运行10.6)块。我认为这将为未来扩展提供最大的灵活性,同时仍保持适当的名称。

答案 1 :(得分:4)

我投票给InsertionOrderDictionary。你钉了它。

答案 2 :(得分:3)

对OrderedDictionary的强烈投票。

单词“ordered”意味着您正在宣传的内容:在遍历项目列表时,有一个已定义的顺序来选择这些项目。 “索引”是一个实现词 - 它更多地讨论了如何实现排序。索引,链表,树...用户不关心;应该隐藏数据结构的这个方面。 “Ordered”是您提供的附加功能的确切字词,无论您如何完成它。

此外,似乎订购的选择可以由用户选择。您无法在数据类型上创建允许用户从字母顺序切换到插入时间排序的方法的任何原因?在默认情况下,用户会选择特定的顺序并坚持使用它,在这种情况下,实现的效率不会低于为每个排序方法创建专用子类的效率。在一些不太常用的情况下,开发人员实际上可能希望根据应用程序上下文对同一数据使用多种不同的排序。 (我可以想到我曾经在那里工作的具体项目,我希望有这样的数据结构。)

称之为OrderedDictionary,因为它正是它的本质。 (坦率地说,我在使用“词典”这个词时遇到了更多的问题,因为这个词很大程度上意味着排序,这种词的流行实现并没有提供它,但那是我的宠儿。你真的应该能够说“字典”并知道排序是按字母顺序排列的 - 因为这就是字典的含义 - 但这种说法对于流行语言中的现有实现来说为时已晚。)并允许用户以他选择的顺序访问。

答案 3 :(得分:2)

自发布此问题以来,我开始倾向于 IndexedDictionary IndexableDictionary 。尽管能够维持任意键排序是有用的,但仅限于插入排序似乎是一种不必要的限制。另外,我的班级已经支持indexOfKey:keyAtIndex:,它们(有目的地)与NSArray的indexOfObject:objectAtIndex:类似。我强烈考虑添加与{NSMutableArray的insertObject:atIndex:匹配的insertObject:forKey:atIndex:

每个人都知道在数组中间插入是低效的,但这并不意味着我们不应该在极少数情况下允许它真正有用。 (此外,如果需要,实施可以秘密使用双向链表或任何其他合适的结构来跟踪订购......)

最大的问题是:“索引”或“可索引”是模糊的还是可能令人困惑的“有序”?人们会想到数据库索引或书籍索引等吗?如果他们认为它是用数组实现的,或者是否可以简化用户对功能的理解,会不会有害?


编辑:鉴于我正在考虑在将来添加适用于NSIndexSet的方法,这个名称更有意义。 (NSArray有-objectsAtIndexes:以及为给定索引处的对象添加/删除观察者的方法。)

答案 4 :(得分:1)

KeyedArray怎么样?

答案 5 :(得分:0)

正如你在上一段中所说,我认为InsertionOrder(ed)Dict(ionary)非常明确;我不知道如何以任何方式解释它,除了按照插入顺序返回键。

答案 6 :(得分:0)

乍一看我是第一个回复 - InsertionOrderDictionary,虽然对于“InsertionOrder”乍看之下有点含糊不清。

你所描述的内容听起来几乎就像一个C ++ STL地图。据我所知,地图是一个包含额外规则的字典,包括订购。 STL简称为“地图”,我认为这是相当贴切的。使用map的技巧是你不能真正地给继承一个点头而不会让它变得多余 - 即“MapDictionary”。这太冗了了。 “地图”有点过于基本,给错误解释留下了很大的空间。

虽然查看文档链接后“CHMap”可能不是一个糟糕的选择。

也许是“CHMappedDictionary”? =)

祝你好运。

编辑:感谢您的澄清,您每天都会学到新的东西。 =)

答案 7 :(得分:0)

通过将索引顺序与插入顺序分离,这不是简单地归结为将数组和Dictionary保持在单个对象中吗?我想我对这类对象的投票是IndexedKeyDictionary

在C#中:

public class IndexedKeyDictionary<TKey, TValue> { 

  List<TKey> _keys;
  Dictionary<TKey, TValue> _dictionary;
  ...

  public GetValueAtIndex(int index) {
    return _dictionary[_keys[index]];
  }

  public Insert(TKey key, TValue val, int index) {
    _dictionary.Add(key, val);

    // do some array massaging (splice, etc.) to fit the new key
    _keys[index] = key;
  }

  public SwapKeyIndexes(TKey k1, TKey k2) {
    // swap the indexes of k1 and k2, assuming they exist in _keys
  }
}

真正酷的是索引值...所以我们有办法对值进行排序并获得新的键盘顺序。就像值是图形坐标一样,我们可以在沿着坐标平面向上/向下移动时读取键(bin名称)。你会怎么称呼这个数据结构?一个IndexedValueDictionary?

答案 8 :(得分:-1)

唯一的区别是allKeys按特定顺序返回键吗?如果是这样,我只需将allKeysSortedallKeysOrderdByInsertion方法添加到标准NSDictionary API。

此广告订单字典的目标是什么?它给程序员和阵列带来了什么好处?