在 Ruby 教程的这一部分中,我们将使用 Ruby 哈希。
Ruby 哈希定义
Ruby 哈希是键-值对的集合。 它类似于数组。 与数组不同,哈希可以将任意对象作为索引。 数组只能具有整数。 哈希值按插入相应键的顺序枚举其值。 哈希有时称为关联数组。
哈希是功能强大的集合。 他们有许多方法可供程序员用来完成工作。
Ruby 哈希创建
可以通过两种基本方式创建哈希:使用new
关键字或哈希字面值。
#!/usr/bin/ruby
names = Hash.new
names[1] = "Jane"
names[2] = "Thomas"
puts names
第一个脚本创建一个哈希并将两个键值对添加到哈希对象中。
names = Hash.new
创建一个哈希对象。
names[1] = "Jane"
names[2] = "Thomas"
我们将两对值添加到哈希中。 数字 1、2 是哈希的键。 键放在方括号内。 名称是属于键的值。
puts names
puts
方法将哈希的字符串表示形式打印到控制台。 它也是哈希的字符串字面值。
$ ./create.rb
{1=>"Jane", 2=>"Thomas"}
从输出中,我们可以看到名称哈希的字面表示。 哈希以大括号为界。 键和值与=>
字符配对。
store
方法可用于使用某些值初始化哈希。 可以使用它代替方括号。
#!/usr/bin/ruby
names = Hash.new
names.store(1, "Jane")
names.store(2, "Thomas")
names.store(3, "Rebecca")
puts names
我们有一个类似的脚本。 这次我们使用store
方法。 该方法将给定键与给定值相关联,并将该对存储在哈希中。
names.store(1, "Jane")
store
方法的第一个参数是键,第二个参数是值。
在第三个脚本中,我们使用哈希字面值表示法创建哈希。 值用大括号括起来。 键值对与=>
字符相关联。
#!/usr/bin/ruby
domains = { "de" => "Germany",
"sk" => "Slovakia",
"hu" => "Hungary",
"us" => "United States",
"no" => "Norway"
}
puts domains["de"]
puts domains["sk"]
我们创建具有 5 对的域哈希。 这次键和值都是字符串类型。
domains = { "de" => "Germany",
"sk" => "Slovakia",
"hu" => "Hungary",
"us" => "United States",
"no" => "Norway"
}
这是哈希字面值表示法。 键值对放在大括号之间。 这些项目用逗号分隔。 使用=>
字符组合将键与值关联。
puts domains["de"]
在这里,我们打印与"de"
键关联的域名名称。
$ ./create3.rb
Germany
Slovakia
这是代码示例的输出。
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 脚本中,我们创建具有五个值的哈希。 我们介绍了三种哈希方法。
puts "The size of the hash is #{names.size}"
size
方法返回哈希的大小。 它是length
方法的同义词。
puts names.keys.inspect
puts names.values.inspect
keys
方法返回哈希的所有键。 values
方法以类似的方式返回哈希的所有值。 返回的数据为数组形式。 为了获得更可读的输出,我们还对返回的数组调用inspect
方法。
$ ./basic.rb
The size of the hash is 5
[1, 2, 3, 4, 5]
["Jane", "Thomas", "Robert", "Julia", "Rebecca"]
我们看到示例的输出。 请注意,最后两个方法的输出是两个数组。
本节的第二个示例介绍了三种不同的哈希方法。
#!/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 脚本创建一个名称哈希。 它在对象上调用三种哈希方法。
names2 = names1.dup
我们通过调用dup
方法来创建哈希的副本。 该方法由父对象的哈希继承。
puts names1.eql? names2
eql?
方法比较两个哈希对象。 在我们的例子中,哈希值是相等的,并且该行打印正确。
puts names1.empty?
empty?
方法检查哈希是否为空。 该行打印false
,因为names1
哈希包含五个项目。
names1.clear
puts names1.empty?
clear
方法从哈希中删除所有项目。 连续调用empty?
方法将返回true
。
$ ./basic2.rb
true
false
true
这是示例输出。
我们有一些方法可以确定哈希中是否存在键或值。
#!/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"
我们用四个对创建一个域哈希。 键是符号。 通常将符号用作键,因为它们更有效。
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"
这两种方法检查两个字符串是否在哈希中。
$ ./has.rb
true
true
false
true
true
true
这是示例的输出。
在本节的最后一个示例中,我们将从哈希中读取值。
#!/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 脚本提供了三种用于读取哈希值的哈希方法。
puts stones.fetch 1
fetch
方法读取给定键的值。
puts stones[2]
方括号可用于获取值。 在我们的例子中,该行将"topaz"
打印到控制台。
puts stones.values_at 1, 2, 3
values_at
方法可用于一步获得多个值。 该方法返回给定键的值的数组。
$ ./read.rb
garnet
topaz
garnet
topaz
opal
This is the output of the example.
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}" }
在上面的示例中,我们介绍了四种方法。 我们使用它们显示哈希的所有键,值以及键和值。
stones.each { |k, v| puts "Key: #{k}, Value: #{v}" }
each
方法为哈希中的每个键调用给定的块,并将键值对作为参数传递。
stones.each_key { |key| puts "#{key}" }
我们使用each_key
方法循环遍历哈希的所有键。 它们被打印到控制台。
stones.each_value { |val| puts "#{val}" }
each_value
可用于循环遍历哈希值。
stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }
each_pair
方法是each
方法的同义词。 我们遍历石头哈希的键和值。
$ ./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 删除哈希中的对
在以下示例中,我们将关注从哈希中删除对的方法。 这包括删除单个对的方法以及可以一步删除多个键值的方法。
#!/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
方法从哈希中删除第一对。 它还以数组形式返回删除的对。
names.delete 4
在这里,我们删除一对4 => "Julia"
。
names.shift
该代码行删除了第一对,即1 => "Jane"
。
$ ./deleteitem.rb
{2=>"Thomas", 3=>"Robert", 5=>"Rebecca"}
在输出中,我们可以看到剩下的哈希对。
reject
和delete_if
方法可以从哈希中删除多对。 这些方法删除对块中给定条件返回true
的对。 两种方法之间有重要区别。 reject
方法适用于哈希的副本,而delete_if
方法适用于原始哈希。
#!/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
该示例使用前面提到的方法删除多个对。
puts names1.reject { |k, v| v =~ /R.*/ }
reject
方法删除适合块中正则表达式的所有值。 返回修改后的哈希,并且原始哈希不会更改。
puts names1
该行的输出确认原始哈希是完整的。
puts names1.delete_if { |k, v| k<=3 }
在这种情况下,我们将删除所有键小于或等于 3 的对。该方法将修改原始哈希。
$ ./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 具有用于添加哈希的方法。
#!/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
方法。
names = names1.merge names2
puts names
names1
和names2
哈希组合在一起。 结果分配给名称哈希。 我们打印新创建的哈希。
$ ./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 方法的对应方法都以感叹号结尾。 此标记没有语法意义,表示方法修改了调用该方法的对象。
#!/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!
方法的区别。
names = names1.merge names2
merge
不会修改names1
哈希。 它可以在其副本上工作。
names = names1.merge! names2
merge!
方法适用于原始哈希。 names1
哈希已更改。
$ ./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 哈希。