# Ruby 哈希

> 原文： [https://zetcode.com/lang/rubytutorial/hashes/](https://zetcode.com/lang/rubytutorial/hashes/)

在 Ruby 教程的这一部分中，我们将使用 Ruby 哈希。

## Ruby 哈希定义

Ruby 哈希是键-值对的集合。 它类似于数组。 与数组不同，哈希可以将任意对象作为索引。 数组只能具有整数。 哈希值按插入相应键的顺序枚举其值。 哈希有时称为关联数组。

哈希是功能强大的集合。 他们有许多方法可供程序员用来完成工作。

## Ruby 哈希创建

可以通过两种基本方式创建哈希：使用`new`关键字或哈希字面值。

```ruby
#!/usr/bin/ruby

names = Hash.new
names[1] = "Jane"
names[2] = "Thomas"

puts names

```

第一个脚本创建一个哈希并将两个键值对添加到哈希对象中。

```ruby
names = Hash.new

```

创建一个哈希对象。

```ruby
names[1] = "Jane"
names[2] = "Thomas"

```

我们将两对值添加到哈希中。 数字 1、2 是哈希的键。 键放在方括号内。 名称是属于键的值。

```ruby
puts names

```

`puts`方法将哈希的字符串表示形式打印到控制台。 它也是哈希的字符串字面值。

```ruby
$ ./create.rb
{1=>"Jane", 2=>"Thomas"}

```

从输出中，我们可以看到名称哈希的字面表示。 哈希以大括号为界。 键和值与`=>`字符配对。

`store`方法可用于使用某些值初始化哈希。 可以使用它代替方括号。

```ruby
#!/usr/bin/ruby

names = Hash.new
names.store(1, "Jane")
names.store(2, "Thomas")
names.store(3, "Rebecca")

puts names

```

我们有一个类似的脚本。 这次我们使用`store`方法。 该方法将给定键与给定值相关联，并将该对存储在哈希中。

```ruby
names.store(1, "Jane")

```

`store`方法的第一个参数是键，第二个参数是值。

在第三个脚本中，我们使用哈希字面值表示法创建哈希。 值用大括号括起来。 键值对与`=>`字符相关联。

```ruby
#!/usr/bin/ruby

domains = { "de" => "Germany",
            "sk" => "Slovakia",
            "hu" => "Hungary",
            "us" => "United States",
            "no" => "Norway"                       
          }

puts domains["de"]
puts domains["sk"]

```

我们创建具有 5 对的域哈希。 这次键和值都是字符串类型。

```ruby
domains = { "de" => "Germany",
            "sk" => "Slovakia",
            "hu" => "Hungary",
            "us" => "United States",
            "no" => "Norway"                       
          }

```

这是哈希字面值表示法。 键值对放在大括号之间。 这些项目用逗号分隔。 使用`=>`字符组合将键与值关联。

```ruby
puts domains["de"]

```

在这里，我们打印与`"de"`键关联的域名名称。

```ruby
$ ./create3.rb 
Germany
Slovakia

```

这是代码示例的输出。

## Ruby 哈希基本操作

在本节中，我们介绍了一些用于 Ruby 哈希基础知识的方法。

```ruby
#!/usr/bin/ruby

names = Hash.new

names[1] = "Jane"
names[2] = "Thomas"
names[3] = "Robert"
names[4] = "Julia"
names[5] = "Rebecca"

puts "The size of the hash is #{names.size}"

puts names.keys.inspect
puts names.values.inspect

```

在上面的 Ruby 脚本中，我们创建具有五个值的哈希。 我们介绍了三种哈希方法。

```ruby
puts "The size of the hash is #{names.size}"

```

`size`方法返回哈希的大小。 它是`length`方法的同义词。

```ruby
puts names.keys.inspect
puts names.values.inspect

```

`keys`方法返回哈希的所有键。 `values`方法以类似的方式返回哈希的所有值。 返回的数据为数组形式。 为了获得更可读的输出，我们还对返回的数组调用`inspect`方法。

```ruby
$ ./basic.rb
The size of the hash is 5
[1, 2, 3, 4, 5]
["Jane", "Thomas", "Robert", "Julia", "Rebecca"]

```

我们看到示例的输出。 请注意，最后两个方法的输出是两个数组。

本节的第二个示例介绍了三种不同的哈希方法。

```ruby
#!/usr/bin/ruby

names1 = Hash.new

names1[1] = "Jane"
names1[2] = "Thomas"
names1[3] = "Robert"
names1[4] = "Julia"
names1[5] = "Rebecca"

names2 = names1.dup

puts names1.eql? names2

puts names1.empty?
names1.clear
puts names1.empty?

```

Ruby 脚本创建一个名称哈希。 它在对象上调用三种哈希方法。

```ruby
names2 = names1.dup

```

我们通过调用`dup`方法来创建哈希的副本。 该方法由父对象的哈希继承。

```ruby
puts names1.eql? names2

```

`eql?`方法比较两个哈希对象。 在我们的例子中，哈希值是相等的，并且该行打印正确。

```ruby
puts names1.empty?

```

`empty?`方法检查哈希是否为空。 该行打印`false`，因为`names1`哈希包含五个项目。

```ruby
names1.clear
puts names1.empty?

```

`clear`方法从哈希中删除所有项目。 连续调用`empty?`方法将返回`true`。

```ruby
$ ./basic2.rb
true
false
true

```

这是示例输出。

我们有一些方法可以确定哈希中是否存在键或值。

```ruby
#!/usr/bin/ruby

domains = { :de => "Germany", :sk => "Slovakia",
            :no => "Norway", :us => "United States"
          }

puts domains.has_key? :de
puts domains.include? :no
puts domains.key? :me
puts domains.member? :sk

puts domains.has_value? "Slovakia"
puts domains.value? "Germany"

```

我们用四个对创建一个域哈希。 键是符号。 通常将符号用作键，因为它们更有效。

```ruby
puts domains.has_key? :de
puts domains.include? :no
puts domains.key? :me
puts domains.member? :sk

```

在这里，我们有四种确定键是否在哈希中的方法。 他们都做同样的事。 它们是同义词。

```ruby
puts domains.has_value? "Slovakia"
puts domains.value? "Germany"

```

这两种方法检查两个字符串是否在哈希中。

```ruby
$ ./has.rb
true
true
false
true
true
true

```

这是示例的输出。

在本节的最后一个示例中，我们将从哈希中读取值。

```ruby
#!/usr/bin/ruby

stones = { 1 => "garnet", 2 => "topaz", 
           3 => "opal", 4 => "amethyst"
         }

puts stones.fetch 1
puts stones[2]
puts stones.values_at 1, 2, 3

```

Ruby 脚本提供了三种用于读取哈希值的哈希方法。

```ruby
puts stones.fetch 1

```

`fetch`方法读取给定键的值。

```ruby
puts stones[2]

```

方括号可用于获取值。 在我们的例子中，该行将`"topaz"`打印到控制台。

```ruby
puts stones.values_at 1, 2, 3

```

`values_at`方法可用于一步获得多个值。 该方法返回给定键的值的数组。

```ruby
$ ./read.rb
garnet
topaz
garnet
topaz
opal

```

This is the output of the example.

## Ruby 哈希迭代

有几种方法可用于遍历 Ruby 哈希。

```ruby
#!/usr/bin/ruby

stones = { 1 => "garnet", 2 => "topaz", 
           3 => "opal", 4 => "amethyst"
         }

stones.each { |k, v| puts "Key: #{k}, Value: #{v}" }
stones.each_key { |key| puts "#{key}" }
stones.each_value { |val| puts "#{val}" }
stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }

```

在上面的示例中，我们介绍了四种方法。 我们使用它们显示哈希的所有键，值以及键和值。

```ruby
stones.each { |k, v| puts "Key: #{k}, Value: #{v}" }

```

`each`方法为哈希中的每个键调用给定的块，并将键值对作为参数传递。

```ruby
stones.each_key { |key| puts "#{key}" }

```

我们使用`each_key`方法循环遍历哈希的所有键。 它们被打印到控制台。

```ruby
stones.each_value { |val| puts "#{val}" }

```

`each_value`可用于循环遍历哈希值。

```ruby
stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }

```

`each_pair`方法是`each`方法的同义词。 我们遍历石头哈希的键和值。

```ruby
$ ./loop.rb
Key: 1, Value: garnet
Key: 2, Value: topaz
Key: 3, Value: opal
Key: 4, Value: amethyst
1
2
3
4
garnet
topaz
opal
amethyst
Key: 1, Value: garnet
Key: 2, Value: topaz
Key: 3, Value: opal
Key: 4, Value: amethyst

```

输出显示石头哈希的键和值，键，值。

## Ruby 删除哈希中的对

在以下示例中，我们将关注从哈希中删除对的方法。 这包括删除单个对的方法以及可以一步删除多个键值的方法。

```ruby
#!/usr/bin/ruby

names = Hash.new

names[1] = "Jane"
names[2] = "Thomas"
names[3] = "Robert"
names[4] = "Julia"
names[5] = "Rebecca"

names.delete 4
names.shift

puts names

```

在脚本中，我们有两种方法：`delete`和`shift`。 `delete`方法删除并返回指定键的值。 `shift`方法从哈希中删除第一对。 它还以数组形式返回删除的对。

```ruby
names.delete 4

```

在这里，我们删除一对`4 => "Julia"`。

```ruby
names.shift

```

该代码行删除了第一对，即`1 => "Jane"`。

```ruby
$ ./deleteitem.rb
{2=>"Thomas", 3=>"Robert", 5=>"Rebecca"}

```

在输出中，我们可以看到剩下的哈希对。

`reject`和`delete_if`方法可以从哈希中删除多对。 这些方法删除对块中给定条件返回`true`的对。 两种方法之间有重要区别。 `reject`方法适用于哈希的副本，而`delete_if`方法适用于原始哈希。

```ruby
#!/usr/local/bin/ruby

names1 = Hash.new

names1[1] = "Jane"
names1[2] = "Thomas"
names1[3] = "Robert"
names1[4] = "Julia"
names1[5] = "Rebecca"

puts names1.reject { |k, v| v =~ /R.*/ }
puts names1
puts names1.delete_if { |k, v| k<=3 }
puts names1

```

该示例使用前面提到的方法删除多个对。

```ruby
puts names1.reject { |k, v| v =~ /R.*/ }

```

`reject`方法删除适合块中正则表达式的所有值。 返回修改后的哈希，并且原始哈希不会更改。

```ruby
puts names1

```

该行的输出确认原始哈希是完整的。

```ruby
puts names1.delete_if { |k, v| k<=3 }

```

在这种情况下，我们将删除所有键小于或等于 3 的对。该方法将修改原始哈希。

```ruby
$ ./massdelete.rb 
{1=>"Jane", 2=>"Thomas", 4=>"Julia"}
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia", 5=>"Rebecca"}
{4=>"Julia", 5=>"Rebecca"}
{4=>"Julia", 5=>"Rebecca"}

```

示例的输出。

## Ruby 在哈希中添加元素

Ruby 的`merge`和`update`方法将（键，值）对添加到哈希。 Ruby 具有用于添加哈希的方法。

```ruby
#!/usr/bin/ruby

names1 = Hash.new

names1[1] = "Jane"
names1[2] = "Thomas"

names2 = Hash.new

names2[3] = "Robert"
names2[4] = "Julia"

names = names1.merge names2
puts names

names = names1.update names2
puts names

```

在 Ruby 脚本中，我们创建两个哈希。 然后我们在它们上应用`merge`和`update`方法。

```ruby
names = names1.merge names2
puts names

```

`names1`和`names2`哈希组合在一起。 结果分配给名称哈希。 我们打印新创建的哈希。

```ruby
$ ./merge.rb
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}

```

如我们所见，最终的哈希包含`names1`和`names2`哈希对。

## Ruby 哈希`merge`和`merge!`方法

在最后一节中，我们回顾了一个常见的 Ruby 习惯用法。 几种 Ruby 方法的对应方法都以感叹号结尾。 此标记没有语法意义，表示方法修改了调用该方法的对象。

```ruby
#!/usr/bin/ruby

names1 = Hash.new

names1[1] = "Jane"
names1[2] = "Thomas"

names2 = Hash.new

names2[3] = "Robert"
names2[4] = "Julia"

names = names1.merge names2
puts names
puts names1

names = names1.merge! names2
puts names
puts names1

```

我们将演示`merge`和`merge!`方法的区别。

```ruby
names = names1.merge names2

```

`merge`不会修改`names1`哈希。 它可以在其副本上工作。

```ruby
names = names1.merge! names2

```

`merge!`方法适用于原始哈希。 `names1`哈希已更改。

```ruby
$ ./merge2.rb
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}
{1=>"Jane", 2=>"Thomas"}
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}

```

这是`merge2.rb`程序的输出。

在本章中，我们使用了 Ruby 哈希。