原文: https://zetcode.com/lang/rubytutorial/hashes/

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

Ruby 哈希定义

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

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

Ruby 哈希创建

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

  1. #!/usr/bin/ruby
  2. names = Hash.new
  3. names[1] = "Jane"
  4. names[2] = "Thomas"
  5. puts names

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

  1. names = Hash.new

创建一个哈希对象。

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

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

  1. puts names

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

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

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

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

  1. #!/usr/bin/ruby
  2. names = Hash.new
  3. names.store(1, "Jane")
  4. names.store(2, "Thomas")
  5. names.store(3, "Rebecca")
  6. puts names

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

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

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

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

  1. #!/usr/bin/ruby
  2. domains = { "de" => "Germany",
  3. "sk" => "Slovakia",
  4. "hu" => "Hungary",
  5. "us" => "United States",
  6. "no" => "Norway"
  7. }
  8. puts domains["de"]
  9. puts domains["sk"]

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

  1. domains = { "de" => "Germany",
  2. "sk" => "Slovakia",
  3. "hu" => "Hungary",
  4. "us" => "United States",
  5. "no" => "Norway"
  6. }

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

  1. puts domains["de"]

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

  1. $ ./create3.rb
  2. Germany
  3. Slovakia

这是代码示例的输出。

Ruby 哈希基本操作

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

  1. #!/usr/bin/ruby
  2. names = Hash.new
  3. names[1] = "Jane"
  4. names[2] = "Thomas"
  5. names[3] = "Robert"
  6. names[4] = "Julia"
  7. names[5] = "Rebecca"
  8. puts "The size of the hash is #{names.size}"
  9. puts names.keys.inspect
  10. puts names.values.inspect

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

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

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

  1. puts names.keys.inspect
  2. puts names.values.inspect

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

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

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

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

  1. #!/usr/bin/ruby
  2. names1 = Hash.new
  3. names1[1] = "Jane"
  4. names1[2] = "Thomas"
  5. names1[3] = "Robert"
  6. names1[4] = "Julia"
  7. names1[5] = "Rebecca"
  8. names2 = names1.dup
  9. puts names1.eql? names2
  10. puts names1.empty?
  11. names1.clear
  12. puts names1.empty?

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

  1. names2 = names1.dup

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

  1. puts names1.eql? names2

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

  1. puts names1.empty?

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

  1. names1.clear
  2. puts names1.empty?

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

  1. $ ./basic2.rb
  2. true
  3. false
  4. true

这是示例输出。

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

  1. #!/usr/bin/ruby
  2. domains = { :de => "Germany", :sk => "Slovakia",
  3. :no => "Norway", :us => "United States"
  4. }
  5. puts domains.has_key? :de
  6. puts domains.include? :no
  7. puts domains.key? :me
  8. puts domains.member? :sk
  9. puts domains.has_value? "Slovakia"
  10. puts domains.value? "Germany"

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

  1. puts domains.has_key? :de
  2. puts domains.include? :no
  3. puts domains.key? :me
  4. puts domains.member? :sk

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

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

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

  1. $ ./has.rb
  2. true
  3. true
  4. false
  5. true
  6. true
  7. true

这是示例的输出。

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

  1. #!/usr/bin/ruby
  2. stones = { 1 => "garnet", 2 => "topaz",
  3. 3 => "opal", 4 => "amethyst"
  4. }
  5. puts stones.fetch 1
  6. puts stones[2]
  7. puts stones.values_at 1, 2, 3

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

  1. puts stones.fetch 1

fetch方法读取给定键的值。

  1. puts stones[2]

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

  1. puts stones.values_at 1, 2, 3

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

  1. $ ./read.rb
  2. garnet
  3. topaz
  4. garnet
  5. topaz
  6. opal

This is the output of the example.

Ruby 哈希迭代

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

  1. #!/usr/bin/ruby
  2. stones = { 1 => "garnet", 2 => "topaz",
  3. 3 => "opal", 4 => "amethyst"
  4. }
  5. stones.each { |k, v| puts "Key: #{k}, Value: #{v}" }
  6. stones.each_key { |key| puts "#{key}" }
  7. stones.each_value { |val| puts "#{val}" }
  8. stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }

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

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

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

  1. stones.each_key { |key| puts "#{key}" }

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

  1. stones.each_value { |val| puts "#{val}" }

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

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

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

  1. $ ./loop.rb
  2. Key: 1, Value: garnet
  3. Key: 2, Value: topaz
  4. Key: 3, Value: opal
  5. Key: 4, Value: amethyst
  6. 1
  7. 2
  8. 3
  9. 4
  10. garnet
  11. topaz
  12. opal
  13. amethyst
  14. Key: 1, Value: garnet
  15. Key: 2, Value: topaz
  16. Key: 3, Value: opal
  17. Key: 4, Value: amethyst

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

Ruby 删除哈希中的对

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

  1. #!/usr/bin/ruby
  2. names = Hash.new
  3. names[1] = "Jane"
  4. names[2] = "Thomas"
  5. names[3] = "Robert"
  6. names[4] = "Julia"
  7. names[5] = "Rebecca"
  8. names.delete 4
  9. names.shift
  10. puts names

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

  1. names.delete 4

在这里,我们删除一对4 => "Julia"

  1. names.shift

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

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

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

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

  1. #!/usr/local/bin/ruby
  2. names1 = Hash.new
  3. names1[1] = "Jane"
  4. names1[2] = "Thomas"
  5. names1[3] = "Robert"
  6. names1[4] = "Julia"
  7. names1[5] = "Rebecca"
  8. puts names1.reject { |k, v| v =~ /R.*/ }
  9. puts names1
  10. puts names1.delete_if { |k, v| k<=3 }
  11. puts names1

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

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

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

  1. puts names1

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

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

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

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

示例的输出。

Ruby 在哈希中添加元素

Ruby 的mergeupdate方法将(键,值)对添加到哈希。 Ruby 具有用于添加哈希的方法。

  1. #!/usr/bin/ruby
  2. names1 = Hash.new
  3. names1[1] = "Jane"
  4. names1[2] = "Thomas"
  5. names2 = Hash.new
  6. names2[3] = "Robert"
  7. names2[4] = "Julia"
  8. names = names1.merge names2
  9. puts names
  10. names = names1.update names2
  11. puts names

在 Ruby 脚本中,我们创建两个哈希。 然后我们在它们上应用mergeupdate方法。

  1. names = names1.merge names2
  2. puts names

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

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

如我们所见,最终的哈希包含names1names2哈希对。

Ruby 哈希mergemerge!方法

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

  1. #!/usr/bin/ruby
  2. names1 = Hash.new
  3. names1[1] = "Jane"
  4. names1[2] = "Thomas"
  5. names2 = Hash.new
  6. names2[3] = "Robert"
  7. names2[4] = "Julia"
  8. names = names1.merge names2
  9. puts names
  10. puts names1
  11. names = names1.merge! names2
  12. puts names
  13. puts names1

我们将演示mergemerge!方法的区别。

  1. names = names1.merge names2

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

  1. names = names1.merge! names2

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

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

这是merge2.rb程序的输出。

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