关于语言不可知:如何访问字典或散列中的第n项?

How do I access the nth item in a dictionary or hash?

我有一个键和值的字典,例如:

1
2
3
4
5
{
    fred: 1,
    dave: 2,
    lily: 3
}

在本例中,如何获取字典中的第二个元素-{dave:2}

背景:我见过这个问题以这样或那样的形式问了很多次,所以我想我应该写一个问答页面作为一个社区wiki,人们可以这可能成为这个问题的典型答案。

此问题适用于词典,因为它们在许多不同的词典中实现。语言。不同的语言使用不同的名称来表示基本上是相同的数据结构-例如,在Perl,python中的字典。在目标C中,它们是NSDictionaryNSMutableDictionary类。


简而言之,你不能-因为字典是无序的键/值对的集合。填充字典的顺序不会保留在内存中。下面是Python中的一个简单示例:

1
2
3
>>> dict = { 'a': 1, 'b': 2, 'c': 3 }
>>> dict # show the value of dict in memory
{'a': 1, 'c': 3, 'b': 2}

正如您所看到的,尽管字典是用顺序A,B,C,打印字典的值显示它们顺序a,c,b。即使该顺序没有保留在内存中;当您向字典中添加更多的键/值对时,上述表达式将继续更改。

这是为什么?

字典经过优化,可快速存储和检索值基于唯一键。实现因语言而异接下来,但通常是这样工作的:

  • 字典由n个元素的标准数组支持。
  • 在存储一个键/值对时,该键将通过一个函数将其转换为整数(一个"散列函数"—因此命名为在Perl中,这个数据结构的"hash")。一个简单的哈希函数对于ASCII字符串键,可以将每个性格。(注意:这不是一个好的哈希算法-只是一个一个简单的例子!)
  • 然后整数除以数组的大小和余数将该除法用作数组的索引。
  • 如果该索引处的数组元素已填充,则使用各种技术中的一种来解决冲突(例如数组元素的内容本身就是一个数组,附加新值及其未显示的键)
  • 检索与存储的工作方式相同:取下钥匙,使用它派生数组索引,然后检索与之关联的值钥匙
  • 支持数组可以随着字典的增长而调整大小:调整大小时数组,字典中的每个元素的散列值除以新的数组大小,产生新的余数,即新的位置在备份数组中。

我是这里的新手,所以还不能添加评论……但这实际上是西蒙对上述答案的评论。

有用的问题和很好的答案,西蒙。您可以在答案中添加另一节,说,因此,这个问题唯一有意义的方法是,如果我们采用如下示例所示的方法

  • 排序(dict),然后获取新排序字典的第n项。这将每次生成完全相同的字典第n项,即使底层数组增长。
  • 枚举(dict)并获取字典中的第n个键