商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Ruby中的Hash哈希类型基本操作方法小结

Ruby中的Hash哈希类型基本操作方法小结

  发布于2026-06-29 阅读(0)

扫一扫,手机访问

提到 Ruby 中的 Hash,很多人第一反应就是“键值对集合”。确实,它和数组一样是 Ruby 里最常用的数据结构之一,但使用起来远比你想象的灵活——键可以是任意对象,值也能随意嵌套。下面我们就从最基础的创建开始,手把手把 Hash 的常用操作理一遍。

1. 创建哈希

创建 Hash 实例和创建数组一样直观。通过 Hash.new 可以快速生成一个空的哈希,你还可以给它指定一个默认值——当访问不存在的键时,就会返回这个默认值:

Ruby中的Hash哈希类型基本操作方法小结

h1 = Hash.new             # 默认值为 nil
h2 = Hash.new("This is my first hash instance")  # 默认值为 "This is my first hash instance"

有了哈希对象之后,添加或删除条目就跟数组一样简单。唯一不同的是,数组的索引只能是整数,而哈希的键(key)可以是任何类型的对象(且必须唯一):

h2["one"] = "北京"
h2["two"] = "上海"
h2["three"] = "深圳"
h2["four"] = "广州"

注意:如果赋值时用了已存在的键,后面的值会覆盖前面的。Ruby 还提供了一种更紧凑的创建和初始化方式——用 => 连接键值对,整体用大括号括起来:

h2 = {
  "one"   => "北京",
  "two"   => "上海",
  "three" => "深圳",
  "four"  => "广州"
}

2. 通过索引存取 Hash 的值

获取值的方法很直接:

puts h2["one"]   # => "北京"

如果键不存在,就会返回之前设置的默认值。另外,使用 default 方法可以获取当前默认值,用 default= 可以重新设置:

puts h1.default
h1.default = "This is set value method"

3. 复制 Hash

和数组一样,直接把一个哈希变量赋给另一个变量,它们会指向同一个对象——修改其中一个,另一个也会跟着变:

h3 = h2
h3["one"] = "西安"
puts h2["one"]   # => "西安"

如果你不想共享引用,可以用 clone 方法创建一个全新的副本:

h4 = h2.clone
h4["one"] = "大连"
puts h2["one"]   # => "西安"(不受影响)

4. Hash 排序

哈希排序不能像数组那样直接用 sort,因为数组里所有元素类型一致(整数),而哈希的键可能是整数、字符串等混合类型。需要自己处理一下:

def sorted_hash(aHash)
  return aHash.sort{ |a,b| a.to_s <=> b.to_s }
end

h1 = {1=>'one', 2=>'two', 3=> 'three'}
h2 = {6=>'six', 5=>'five', 4=> 'four'}
h3 = {'one'=>'A', 'two'=>'B','three'=>'C'}
h4 = h1.merge(h2)      # 合并 hash
h5 = h1.merge(h3)

p(h4)
p(h4.sort)
p(h5)
p(sorted_hash(h5))

结果如下:

{5=>"five", 6=>"six", 1=>"one", 2=>"two", 3=>"three", 4=>"four"}
[[1, "one"], [2, "two"], [3, "three"], [4, "four"], [5, "five"], [6, "six"]]
{"two"=>"B", "three"=>"C", 1=>"one", 2=>"two", "one"=>"A", 3=>"three"}
[[1, "one"], [2, "two"], [3, "three"], ["one", "A"], ["three", "C"], ["two", "B"]]

实际上,Hash 的 sort 方法内部会把哈希转换成以 [key, value] 为元素的数组,然后再用数组的排序逻辑进行排序。

5. Hash 类常用方法

方法 说明
size() 返回 Hash 对象的长度
length() 返回 Hash 对象的长度
include?(key) 判断是否包含指定的 key
has_key?(key) 判断是否包含指定的 key
delete(key) 删除指定 key 对应的元素
keys() 返回由所有 key 组成的数组
values() 返回由所有 value 组成的数组

举个例子:

student = {
  "name"   => "Steve",
  "age"    => 22,
  "Gender" => "male"
}

p student.keys                # => ["name", "Gender", "age"]
p student.values              # => ["Steve", "male", 22]
puts student.include?("age")  # => true
puts student.size             # => 3
student.delete("Gender")
puts student.has_key?("Gender") # => false
puts student.size             # => 2

6. Hash 的转换使用

当面对多层嵌套的哈希时,读写操作容易变得混乱。一个常见的解决方案是把哈希转换成对象,让每一个键都能像属性一样直接访问。下面的 HashObj 类就是为此设计的:

class HashObj
  class << self
    def load_from_hash(hash)
      if hash.instance_of? Hash
        obj = HashObj.new
        hash.each{|k,v| obj.send :def_sget_method, k, HashObj.load_from_hash(v) }
        obj
      elsif hash.instance_of? Array
        hash.map{|m| HashObj.load_from_hash(m) }
      else
        hash
      end
    end
  end

  def attributes
    hash = {}
    @@reg ||= /=/
    self.singleton_methods.reject{|x| @@reg =~ x.to_s}.each do |m|
      v = self.send(m)
      if v.instance_of? HashObj
        real_v = v.attributes
      elsif v.instance_of? Array
        real_v = []
        v.each do |l|
          if l.instance_of? HashObj
            real_v << l.attributes
          else
            real_v << l
          end
        end
      else
        real_v = v
      end
      hash[m] = real_v
    end
    hash
  end

  protected
  def def_sget_method(name, val)
    self.instance_variable_set "@#{name}", val

    self.define_singleton_method "#{name}=" do |n_val|
      instance_variable_set "@#{name}", n_val
    end

    self.define_singleton_method name do
      instance_variable_get "@#{name}"
    end
  end
end

使用示例:

hash = {
  name: 'jack',
  age: 22,
  phone: ['61900871', '8787876'],
  basic_info: { country: 'USA', city: 'New York' }
}

obj = HashObj.load_from_hash hash
obj.name              # => 'jack'
obj.age               # => 22
obj.phone             # => ['61900871', '8787876']
obj.basic_info        # => 
obj.basic_info.country # => 'USA'
obj.attributes == hash # => true

obj.age = 30
obj.attributes
# => {:name=>"jack", :age=>30, :phone=>["61900871", "8787876"], :basic_info=>{:country=>"USA", :city=>"New York"}}

这样一来,深层嵌套的哈希读写就变得和普通对象一样清晰了。

本文转载于:https://www.jb51.net/article/86104.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

产品推荐

热门关注