具有连续编号键的哈希与数组有何不同



考虑:

foo = {
    0 =>    "a",
    1 =>    "b",
    2 =>    "c"
}
bar = ["a","b","c"]

从功能上讲,这些对我来说似乎是一样的。区别是否只是因为它们是不同的数据类型,即使数据本身实际上是相同的?

我觉得数组应该是哈希的子类,区别在于键是隐含的,因此不需要由程序员显式设置。

语义和实现都存在差异。

从语义上讲,数组是有序值的列表。从列表中删除项目会移动列表中的所有其他项目。列表中有头部和尾部,您可以在特定位置插入其中。列表中可能存在间隙(在给定索引中没有存储任何值)。

相比之下,哈希不一定有任何定义的顺序(尽管它们在 Ruby 1.9+ 中确实如此),没有头部或反面,迭代中不能有间隙,并且不允许在可迭代顺序的中间插入(至少,无需诉诸整个哈希)。

在实施方面,它们是黑夜和白天。数组是更简单的数据结构 - 在底层,它们只是一个连续的内存块,由(索引 * 结构大小)索引。获取/设置都是 O(1)。另一方面,哈希往往是链表的列表。通过哈希函数传递键,以确定值要存储在集合中的哪个链表上或从哪个链表中检索,然后迭代链表以检索该值。插入为 O(1),检索为 O(n log n)。

虽然 PHP 背景可能会让人觉得数组应该是 Hash 的一个子类,因为 PHP 将它们合并在一起,但它们是非常不同的数据结构,具有不同的目的和行为,实际上应该保持独立。

你的同化不会延伸到一些自然定义的概念。

例如,加法+自然是在数组上定义的:

["a", "b", "c"] + ["d", "e", "f"]
# => ["a", "b", "c", "d", "e", "f"]

如果你遵循你的同化并对哈希对应物做类似的事情 merge ,你会得到不同的结果:

{0 => "a", 1 => "b", 2 => "c"}.merge({0 => "d", 1 => "e", 2 => "f"}
# => {0 => "d", 1 => "e", 2 => "f"}

编辑我认为这种差异背后的原因是,从 0 开始的索引的连续编号对于数组是自动的。无论您对数组执行什么操作,始终满足条件。为了保持同化,您必须在"哈希的数组部分"中添加一种机制来执行此操作。

数组

在解析数据时会更有效,因为MRI(Matz的Ruby解释器 - Ruby解释器)必须将哈希中的键评估为字符串/符号而不是整数索引值。

最新更新