6

我喜欢在需要保留键顺序的关联数组时使用collections.OrderedDict 。我最好的例子是解析或创建 csv 文件,在对象中隐式保留列的顺序很有用。

但我担心这是不好的做法,因为在我看来,关联数组的整个概念是键的顺序永远不重要,任何依赖排序的操作都应该只使用列表,因为这就是为什么列表存在(这可以为上面的 csv 示例完成)。我没有这方面的数据,但我敢打赌,列表的性能普遍优于 OrderedDict。

所以我的问题是:OrderedDict 是否有任何真正引人注目的用例?csv 用例是应该在哪里使用的一个很好的例子还是一个不好的例子?

4

5 回答 5

6

但我担心这是不好的做法,因为在我看来,关联数组的整个概念是键的顺序永远不重要,

废话。这不是“关联数组的整个概念”。只是顺序很少重要,所以我们默认放弃顺序以获得概念上更简单(和更有效)的数据结构。

并且任何依赖于排序的操作都应该只使用列表,因为这就是列表存在的原因

停在那里!想一想。会如何使用列表?作为(键,值)对的列表,具有唯一键,对吗?恭喜你,我的朋友,你刚刚重新发明了 OrderedDict,只是用了一个糟糕的 API,而且速度真的很慢。对有序映射的任何概念上的反对也将适用于这种自组织数据结构。幸运的是,这些反对意见是无稽之谈。有序映射非常好,它们只是与无序映射不同。给它一个恰当命名的专用实现,具有良好的 API 和良好的性能,可以改善人们的代码。

除此之外:列表只是一种有序的数据结构。虽然它们在某种程度上是通用的,因为您几乎可以从某种列表组合中提取所有数据结构(如果您向后弯曲),但这并不意味着您应该始终使用列表。

我没有这方面的数据,但我敢打赌,列表的性能普遍优于 OrderedDict。

数据(结构)没有(不)有性能。对数据(结构)的操作都有。因此,这取决于您对哪些操作感兴趣。如果您只需要一个对列表,那么一个列表显然是正确的,并且对其进行迭代或索引它非常有效。但是,如果您想要一个也已排序的映射,或者甚至是映射功能的一小部分(例如处理重复键),那么单独的列表非常糟糕,正如我在上面已经解释的那样。

于 2013-06-30T18:59:13.270 回答
2

对于您的特定用例(编写 csv 文件),不需要有序的 dict。相反,使用DictWriter.

就我个人而言,OrderedDict当我需要一些 LIFO/FIFO 访问时,我会使用它,甚至有一个popitem方法。老实说,我想不出一个好的用例,但是PEP-0327中提到的属性顺序是一个很好的用例:

XML/HTML 处理库目前放弃了属性的排序,使用列表而不是字典,这使得过滤变得很麻烦,或者实现了自己的有序字典。这会影响 ElementTree、html5lib、Genshi 和更多库。

如果您曾经质疑为什么 Python 中有某些特性,那么 PEP 是一个很好的起点,因为那里详细说明了导致包含该特性的理由。

于 2013-06-30T18:42:00.433 回答
0

大概一个评论就够了……

我认为如果您在不需要它的地方使用它(顺序无关紧要,普通的 dict 就足够了),那将是有问题的。否则代码可能会比使用列表更简单。

这对任何语言构造/库都有效 - 如果它使您的代码更简单,请使用更高级别的抽象/实现。

于 2013-06-30T18:42:43.653 回答
0

只要您对这种数据结构感到满意,并且它符合您的需求,为什么要关心?也许它不是更有效的(在速度等方面),但是,如果它在那里,那显然是因为它在某些情况下很有用(或者没有人会想到写它)。

您基本上可以在 Python 中使用三种类型的关联数组:

  1. 经典的哈希表(完全没有顺序)
  2. OrderedDict(反映对象创建方式的顺序)
  3. 和二叉树 - 这不在标准库中 - 以自定义顺序(不一定是字母顺序)完全按照您的需要对它们的键进行排序。

所以,事实上,键的顺序重要。只需选择您认为更适合完成这项工作的结构。

于 2013-06-30T18:58:09.610 回答
-1

对于 CSV 和重复键的类似结构,使用命名元组。这是两全其美的。

于 2013-06-30T18:31:33.207 回答