2009-10-15 43 views
0

我正在编写一个接口以排序的对象集合。像往常一样,我把它留给用户来指定这些项目如何排序。然而,我目前在提供键值接口(其中,排序键明确与值分离)或仅有值的接口(其中值或者是排序键,或者用户必须处理单独的排序键通过传递一些比较函数)。将分类值抽象为键值

在我看来,键值接口强制用户始终拥有与该值分离的键,即使某些值自然形成了自己的键。它确实带走了用户处理密钥的责任,但是在使用我的API时可能会导致更简单和更清晰的用户代码。只有值的接口允许对他们自己的键进行更紧凑的值表示,但是在有自然键值区分的情况下,强制用户跟踪和处理他们自己的键。

当然有文献支持这两种方法,尽管在我看来(在这方面可能是错误的),旧的文献往往倾向于只采用价值的方法,而较新的文献则倾向于采用键值方法。

我很好奇你在这些情况下的喜好。我们是否已经到了一个通常比另一个更受欢迎的时间点?如果不是,你通常使用什么,为什么?

回答

1

你似乎之间是所谓的被撕裂(各种语言,各种区别,但本质上...)

  • 词典(又名一个Hashtable甚至哈希)
  • 的List /阵列

这两种类型的容器有不同的用途,虽然有一些调整,但很少有List可以做到这一点,Dictionary不能。这仅仅是因为词典有更多的信息。

一般来说它是比隐含更明确。
如果我递给你一个"2 dollars blue crayon"(一个列表),你会推断它是一个具有以下属性的对象:{Price = 2$, Color = blue, Type = Crayon}(Dictionary)。然而,这种解析(在需要时)需要努力和知识域或数据的隐式结构;字典方法可以让你以通用的方式处理信息。

有些情况下,列表是“更好”的,但这通常与技术/操作考虑有关,而不是列表方法的固有属性。例如,为了使用简单的全文本引擎来实现搜索索引,可能需要将所有属性混合在一起(这反映了最终用户键入未标记的关键字的方式,期望它们可以在任何属性中找到)。

实用建议,响应于该问题是提供:

  • 暴露出两个列表的使用/行为和字典
  • 优化的(大小向和/或API在空间方面,取决于它的重要性)实现,它保留了List的一些方法在性能方面的“边缘”,至少在容器被用作字典之前。

除非先验明显的关注关于性能(例如:容器将接收项目数以万计,会有成千上万的容器实例,容器就过境过慢通道等),我会将注意力集中在API的第一个上,让我轻松实现,例如基于字典。在以后的日子里,如果这是必要的,可以修改实施,例如使用两个列表和一个地图模式。

最后一件事:有很多它提供这种多态容器的库(甚至是语言内建)的:也许看看是否有适合你的目标系统/语言......

+0

您已经理解了这个问题,但是如果您推荐的是键值(字典)的仅值(列表)结构,请提供一些推理。 – sooniln 2009-10-15 20:29:49

+0

在我看来,人们可以将字典视为列表的一个(几乎)特殊情况(而我们至少在讨论排序后的集合)。列表将摘要排除在排序关键字之上,让用户以任何方式处理它,而词典则将明确的排序关键字附加到其值列表中。这使列表更通用,尽管可能并不总是如此高效。 – sooniln 2009-10-15 20:52:13

+0

感谢您的详细解答。我倾向于一个价值唯一的实现,但您的意见,加上我自己的更多研究,已经推动我迈向一个关键价值的方法。毕竟,从概念上讲,Set在某些方面可能比Map更高的抽象,你可以从Map实现Set,但反之亦然。 这对我来说更像是一个练习,而不是我需要的东西,但不幸的是,我目前工作的语言(C#)遇到了一些严重的设计缺陷,当涉及到这样的容器时:/ – sooniln 2009-10-15 21:01:10

0

好吧,这似乎回答你的要求。当没有指定keyseelctor时,集合假定订单是在物品本身上定义的 - 它们应该可能实现IComparable。 否则 - 如果您有理论上可以通过多种方式进行比较的项目,您可以指定一个按键选择器,该按键选择器将自行返回IComaprable项目的投影。

举例来说,如果你有一类人用姓名和年龄,并希望按年龄保持排序列表,您可以创建以下方式收集:

新OrderedCollection(人=>人士);

顺便检查一下.Net附带的SortedDictionary和SortedList集合。他们可能派上用场。

+0

你能详细说明为什么你会做出这样的选择吗? – sooniln 2009-10-15 20:27:55

0

刚关于一个列表可以做的字典可以做的任何事情,如果为key + value创建一个包装器结构或对象,并且简单地将值部分留空。字典唯一不能做的就是添加一个特定类型的值,然后用一个返回该类型的枚举器直接响应GetEnumerator请求。然而,围绕字典构造一个包装类来做到这一点很容易。

然而,字典和列表之间的主要区别在于它们处理关键部分相同但Value部分不相同的记录。尽管我并不是Dictionary处理事物的方式(默认的索引属性使用'replace'语义,而add方法使用fail-if存在的语义;我的偏好本来是为“add “),它允许更改与特定键相关联的值。一个“列表”只能通过删除旧值并添加一个新值来尝试去做,这个操作可能会引起语义问题。