POSTS
第十一章、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是哈希表的键。键放在中括号里。names是属于键的值。
puts names
打印哈希表。
$ ./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"]
创建哈希表domains包含5对内容。这里键和值都是字符串。
$ ./create3.rb
Germany
Slovakia
例子的输出结果。
基本用法
这一节我们展示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
上面的脚本中创建了一个有5个值的哈希表,介绍了哈希表的三个方法。
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?
创建了一个names哈希表,对该对象调用了三个方法。
names2 = names1.dup
通过dup方法创建了一个副本。
puts names1.eql? names2
eql?方法比较两个哈希表对象是否相等。这里是相同的,打印true。
puts names1.empty?
empty?方法检查哈希表是否为空。这行打印false,因为names1有5项数据。
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"
创建了一个有4对数据的哈希表domains。键是用的符号,因为它更有效。
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
这个脚本展示了三个读取值的方法。
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
例子的输出结果。
循环遍历哈希表
有一些方法可以用于循环遍历哈希表。
#!/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
输出结果。
删除键值对
接下来的例子关注哈希表的删除。
#!/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"}
输出结果。
添加内容
merge和update方法可以给哈希表添加键值对。
#!/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
这个脚本中我们创建了两个哈希表,然后对它们调用了merge和update方法。
names = names1.merge names2
puts names
合并names1和names2,结果分配给names。
$ ./merge.rb
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}
{1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}
最后的哈希表包含了names1和names2的内容。
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的哈希表。zetcode原文地址