跳至内容

哈希

一个 Hash 是一个通用的键值对集合,将类型为 K 的键映射到类型为 V 的值。

哈希通常使用哈希字面量创建,哈希字面量由花括号 ({ }) 括起来,其中包含使用 => 作为键和值之间分隔符且用逗号 , 分隔的键值对列表。

{"one" => 1, "two" => 2}

泛型类型参数

K 和值 V 的泛型类型参数分别从字面量中键或值的类型推断得出。当所有类型都相同时,K/V 等于该类型。否则,它将分别为所有键类型或值类型的并集。

{1 => 2, 3 => 4}   # Hash(Int32, Int32)
{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32)

可以通过在右括号后紧跟 of(用空格分隔)、键类型 (K) 后跟 => 作为分隔符以及值类型 (V) 来指定显式类型。这会覆盖推断出的类型,例如,可以用来创建一个最初只包含某些类型的哈希,但也可以接受其他类型的哈希。

空哈希字面量始终需要类型规范

{} of Int32 => Int32 # => Hash(Int32, Int32).new

类哈希类型字面量

Crystal 支持哈希和类哈希类型的附加字面量。它由类型的名称后跟花括号 ({}) 括起来的逗号分隔的键值对列表组成。

Hash{"one" => 1, "two" => 2}

只要类型具有无参数构造函数并响应 []=,就可以使用此字面量。

HTTP::Headers{"foo" => "bar"}

对于像 HTTP::Headers 这样的非泛型类型,这等效于

headers = HTTP::Headers.new
headers["foo"] = "bar"

对于泛型类型,泛型类型会像哈希字面量一样从键和值的类型推断得出。

MyHash{"foo" => 1, "bar" => "baz"}

如果 MyHash 是泛型,上面的代码等效于

my_hash = MyHash(typeof("foo", "bar"), typeof(1, "baz")).new
my_hash["foo"] = 1
my_hash["bar"] = "baz"

类型参数可以作为类型名称的一部分显式指定

MyHash(String, String | Int32){"foo" => "bar"}