0

我正在为已排序的对象集合编写接口。像往常一样,我让用户来指定这些项目的排序方式。然而,我目前在提供键值接口(排序键与值显式分离)或仅值接口(值也是排序键,或者用户必须处理单独的排序)之间感到困惑键通过传入一些比较函数)。

在我看来,键值接口迫使用户始终拥有与值分开的键,即使某些值自然形成了自己的键。然而,它确实免除了用户处理密钥的责任,在使用我的 API 时可能会导致更简单和更清晰的用户代码。仅值接口允许更紧凑地表示作为其自己的键的值,但在存在自然键值区别的情况下强制用户跟踪和处理自己的键。

当然,有文献支持这两种方法,尽管在我看来(这可能是错误的)旧文献倾向于仅使用价值方法,而较新的文献更喜欢键值方法。

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

4

3 回答 3

1

您似乎在所谓的(在不同的语言中,有不同的区别,但本质上......)

  • 字典(又名哈希表,甚至是哈希)
  • 一个列表/数组

这两种类型的容器服务于不同的目的,尽管经过一些调整,列表可以做的几乎没有字典不能做的事情。那只是因为字典有更多的信息。

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

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

针对这个问题,一个实用的建议是提供:

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

除非事先对性能有明显的担忧(例如:容器将接收数万个项目,会有数千个容器实例,容器将通过慢速通道传输等),否则我会先关注 API,放轻松与实现,例如基于字典。稍后,如果有必要,可以修改实现,例如使用两个列表和一个映射模式。

最后一件事:有很多库(甚至是语言内置)提供这种多态容器:也许看看是否有一个可用于您的目标系统/语言......

于 2009-10-15T20:22:26.970 回答
0

好吧,这似乎可以满足您的要求。当没有指定 keyseelctor 时,集合假定排序是在项目本身上定义的——它们可能应该实现 IComparable。否则-如果您有理论上可以通过多种方式进行比较的项目-您可以指定一个键选择器,该键选择器将返回一个项目的投影,​​该项目本身就是 ICmaprable。

例如,如果您有一个具有名称和年龄的类 Person,并且您希望按年龄保留一个排序列表,您可以通过以下方式创建集合:

新的 OrderedCollection(person => person.Age);

顺便说一句,请查看 .Net 附带的 SortedDictionary 和 SortedList 集合。他们可能会派上用场。

于 2009-10-15T20:22:03.443 回答
0

列表可以做的几乎所有字典都可以做的事情,如果一个人为键+值创建一个包装结构或对象,并且只是将值部分留空。字典唯一不能真正做的事情是添加特定类型的值,然后使用返回该类型的枚举器直接响应 GetEnumerator 请求。但是,很容易围绕字典构建一个包装类来做到这一点。

然而,字典和列表之间的主要区别在于它们处理键部分相同但值部分不同的记录的方式。虽然我不是 Dictionary 处理事物方式的忠实粉丝(默认索引属性使用“替换”语义,而 add 方法使用 fail-if-exists 语义;我的偏好是为“添加”设置一个模式参数"),它允许更改与特定键关联的值。“列表”只能通过删除旧值并添加新值来尝试做到这一点,这种操作可能会导致语义问题。

于 2010-10-25T19:58:51.303 回答