当前位置: 首页>>编程示例 >>用法及示例精选 >>正文


Ruby Hash类用法及代码示例

本文简要介绍ruby语言中 Hash类 的用法。

哈希将其每个唯一键映射到特定值。

Hash 与 Array 有某些相似之处,但是:

  • 数组索引始终是整数。

  • 哈希键可以(几乎)是任何对象。

哈希数据语法

哈希数据的旧语法使用“哈希火箭”=>

h = {:foo => 0, :bar => 1, :baz => 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

或者,但仅对于作为符号的哈希键,您可以使用更新的 JSON-style 语法,其中每个裸词都成为符号:

h = {foo: 0, bar: 1, baz: 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

您还可以使用字符串代替裸词:

h = {'foo': 0, 'bar': 1, 'baz': 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

您可以混合样式:

h = {foo: 0, :bar => 1, 'baz': 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

但是尝试 JSON-style 语法来获取不是裸词或字符串的键是错误的:

# Raises SyntaxError (syntax error, unexpected ':', expecting =>):
h = {0: 'zero'}

Hash 值可以省略,这意味着该值将通过键的名称从上下文中获取:

x = 0
y = 100
h = {x:, y:}
h # => {:x=>0, :y=>100}

常见用途

您可以使用 Hash 为对象命名:

person = {name: 'Matz', language: 'Ruby'}
person # => {:name=>"Matz", :language=>"Ruby"}

您可以使用 Hash 为方法参数命名:

def some_method(hash)
  p hash
end
some_method({foo: 0, bar: 1, baz: 2}) # => {:foo=>0, :bar=>1, :baz=>2}

注意:当方法调用的最后一个参数是 Hash 时,可以省略花括号:

some_method(foo: 0, bar: 1, baz: 2) # => {:foo=>0, :bar=>1, :baz=>2}

您可以使用哈希来初始化对象:

class Dev
  attr_accessor :name, :language
  def initialize(hash)
    self.name = hash[:name]
    self.language = hash[:language]
  end
end
matz = Dev.new(name: 'Matz', language: 'Ruby')
matz # => #<Dev: @name="Matz", @language="Ruby">

创建哈希

您可以使用以下命令显式创建 Hash 对象:

您可以使用以下方法将某些对象转换为哈希:

您可以通过调用方法 Hash.new 创建一个哈希。

创建一个空哈希:

h = Hash.new
h # => {}
h.class # => Hash

您可以通过调用方法 Hash.[] 创建一个哈希。

创建一个空哈希:

h = Hash[]
h # => {}

创建一个带有初始条目的哈希:

h = Hash[foo: 0, bar: 1, baz: 2]
h # => {:foo=>0, :bar=>1, :baz=>2}

您可以使用其文字形式(大括号)创建一个 Hash。

创建一个空哈希:

h = {}
h # => {}

创建一个带有初始条目的哈希:

h = {foo: 0, bar: 1, baz: 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

哈希值基础

检索哈希值的最简单方法(实例方法 [] ):

h = {foo: 0, bar: 1, baz: 2}
h[:foo] # => 0

创建或更新哈希值的最简单方法(实例方法 []= ):

h = {foo: 0, bar: 1, baz: 2}
h[:bat] = 3 # => 3
h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
h[:foo] = 4 # => 4
h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3}

删除哈希条目的最简单方法(实例方法 delete ):

h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {:foo=>0, :baz=>2}

入场令

Hash 对象按其创建顺序显示其条目。这可见于:

  • 迭代方法,例如 eacheach_keyeach_paireach_value

  • 其他顺序敏感的方法,例如 shiftkeysvalues

  • 方法 inspect 返回的字符串。

根据给定条目,新哈希具有其初始排序:

h = Hash[foo: 0, bar: 1]
h # => {:foo=>0, :bar=>1}

最后添加新条目:

h[:baz] = 2
h # => {:foo=>0, :bar=>1, :baz=>2}

更新值不会影响顺序:

h[:baz] = 3
h # => {:foo=>0, :bar=>1, :baz=>3}

但是重新创建已删除的条目可能会影响顺序:

h.delete(:foo)
h[:foo] = 5
h # => {:bar=>1, :baz=>3, :foo=>5}

哈希键

哈希键等价

当两个对象的hash 值相同并且两个对象彼此为eql? 时,两个对象被视为相同的哈希键。

修改活动哈希键

在使用时修改哈希键会损坏哈希的索引。

此哈希具有数组键:

a0 = [ :foo, :bar ]
a1 = [ :baz, :bat ]
h = {a0 => 0, a1 => 1}
h.include?(a0) # => true
h[a0] # => 0
a0.hash # => 110002110

修改数组元素a0[0] 会改变其哈希值:

a0[0] = :bam
a0.hash # => 1069447059

并损坏哈希索引:

h.include?(a0) # => false
h[a0] # => nil

您可以使用方法 rehash 修复哈希索引:

h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
h.include?(a0) # => true
h[a0] # => 0

字符串键始终是安全的。这是因为作为键传递的未冻结字符串将被重复和冻结的字符串替换:

s = 'foo'
s.frozen? # => false
h = {s => 0}
first_key = h.keys.first
first_key.frozen? # => true

用户定义的哈希键

要用作哈希键,对象必须实现方法 hasheql? 。注意:如果哈希使用 compare_by_identity ,则此要求不适用,因为比较将依赖于键的对象 id 而不是 hasheql?

Object 定义了hasheq? 的基本实现,使每个对象成为不同的键。通常,用户定义的类将希望覆盖这些方法以提供有意义的行为,或者例如继承对这些具有有用定义的 Struct。

hash 的典型实现基于对象的数据,而 eql? 通常别名为重写的 == 方法:

class Book
  attr_reader :author, :title

  def initialize(author, title)
    @author = author
    @title = title
  end

  def ==(other)
    self.class === other &&
      other.author == @author &&
      other.title == @title
  end

  alias eql? ==

  def hash
    @author.hash ^ @title.hash # XOR
  end
end

book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'

reviews = {}

reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'

reviews.length #=> 1

默认值

[] values_at dig 方法需要返回与某个键关联的值。当未找到该键时,该值将由其默认 proc(如果有)或默认值(最初为“nil”)确定。

您可以使用方法 default 检索默认值:

h = Hash.new
h.default # => nil

您可以通过将参数传递给方法 Hash.new 或使用方法 default= 来设置默认值

h = Hash.new(-1)
h.default # => -1
h.default = 0
h.default # => 0

当未找到 key 时,将为 [] values_at dig 返回此默认值:

counts = {foo: 42}
counts.default # => nil (default)
counts[:foo] = 42
counts[:bar] # => nil
counts.default = 0
counts[:bar] # => 0
counts.values_at(:foo, :bar, :baz) # => [42, 0, 0]
counts.dig(:bar) # => 0

请注意,使用默认值而不重复。不建议将默认值设置为可变对象:

synonyms = Hash.new([])
synonyms[:hello] # => []
synonyms[:hello] << :hi # => [:hi], but this mutates the default!
synonyms.default # => [:hi]
synonyms[:world] << :universe
synonyms[:world] # => [:hi, :universe], oops
synonyms.keys # => [], oops

要将可变对象用作默认值,建议使用默认 proc

默认过程

当设置了 Hash 的默认 proc 时(即不是 nil ),方法 [] 返回的默认值仅由默认 proc 确定。

您可以使用方法 default_proc 检索默认过程:

h = Hash.new
h.default_proc # => nil

您可以通过使用块调用 Hash.new 或调用方法 default_proc= 来设置默认过程

h = Hash.new { |hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
h.default_proc = proc { |hash, key| "Default value for #{key.inspect}" }
h.default_proc.class # => Proc

当设置了默认过程(即不是 nil )并且使用不存在的键调用方法 [] 时, [] 使用 Hash 对象本身和缺少的键调用默认过程,然后返回proc的返回值:

h = Hash.new { |hash, key| "Default value for #{key}" }
h[:nosuch] # => "Default value for nosuch"

请注意,在上面的示例中,没有为键 :nosuch 创建条目:

h.include?(:nosuch) # => false

但是,proc 本身可以添加一个新条目:

synonyms = Hash.new { |hash, key| hash[key] = [] }
synonyms.include?(:hello) # => false
synonyms[:hello] << :hi # => [:hi]
synonyms[:world] << :universe # => [:universe]
synonyms.keys # => [:hello, :world]

请注意,设置默认 proc 将清除默认值,反之亦然。

这里有什么

首先,其他地方有什么。类哈希:

在这里,类 Hash 提供了有用的方法:

类 Hash 还包括来自模块 Enumerable 的方法。

创建哈希的方法

Hash[]

返回用给定对象填充的新哈希。

Hash.new

返回一个新的空哈希。

::try_convert

返回从给定对象创建的新哈希。

设置哈希状态的方法

Hash.compare_by_identity

设置 self 以在比较键时仅考虑身份。

Hash.default =

将默认值设置为给定值。

Hash.default_proc =

将默认 proc 设置为给定的 proc。

rehash

通过重新计算每个键的哈希索引来重建哈希表。

查询方法

Hash.any?

返回是否有任何元素满足给定条件。

compare_by_identity?

返回比较键时哈希是否只考虑身份。

Hash.default

返回默认值,或给定键的默认值。

Hash.default_proc

返回默认过程。

Hash.empty?

返回是否没有条目。

Hash.eql? object

返回给定对象是否等于 self

Hash.hash

返回整数哈希码。

has_value?

返回给定对象是否是 self 中的值。

include? , has_key? , member? , key?

返回给定对象是否是 self 中的键。

length , size

返回条目数。

value?

返回给定对象是否是 self 中的值。

比较方法

#

返回self 是否是给定对象的真子集。

#

返回self 是否是给定对象的子集。

#==

返回给定对象是否等于 self

#>

返回self 是否是给定对象的正确超集

#>=

返回self 是否是给定对象的正确超集。

获取方法

Hash.hash[key]

返回与给定键关联的值。

Hash.assoc

返回包含给定键及其值的 2 元素数组。

Hash.dig

返回由给定键和附加参数指定的嵌套对象中的对象。

Hash.fetch

返回给定键的值。

Hash.fetch_values

返回包含与给定键关联的值的数组。

Hash.key

返回具有给定值的first-found 条目的键。

Hash.keys

返回包含 self 中所有键的数组。

Hash.rassoc

返回一个 2 元素数组,该数组由具有给定值的 first-found 条目的键和值组成。

Hash.values

返回一个包含self中所有值的数组/

Hash.values_at

返回一个包含给定键值的数组。

分配方法

[]= , store

将给定键与给定值相关联。

Hash.merge

返回通过将每个给定哈希合并到 self 的副本中形成的哈希。

merge! , update

将每个给定的哈希合并到 self 中。

Hash.replace

self 的全部内容替换为 givan 哈希的内容。

删除方法

这些方法从 self 中删除条目:

clear

self 中删除所有条目。

Hash.compact!

self 中删除所有 nil 值条目。

Hash.delete

删除给定键的条目。

Hash.delete_if

删除给定块选择的条目。

filter! , select!

仅保留给定块选择的那些条目。

Hash.keep_if

仅保留给定块选择的那些条目。

Hash.reject!

删除给定块选择的条目。

Hash.shift

删除并返回第一个条目。

这些方法返回 self 的副本,其中删除了一些条目:

Hash.compact

返回 self 的副本,其中删除了所有 nil 值条目。

Hash.except

返回 self 的副本,其中删除了指定键的条目。

filter , select

返回 self 的副本,其中仅包含给定块选择的条目。

Hash.reject

返回 self 的副本,其中删除了给定块指定的条目。

Hash.slice

返回包含给定键的条目的哈希。

迭代方法

each , each_pair

使用每个键值对调用给定块。

Hash.each_key

使用每个键调用给定的块。

Hash.each_value

使用每个值调用给定块。

转换方法

inspect , to_s

返回包含哈希条目的新 String

Hash.to_a

返回一个新的 2 元素数组;每个嵌套数组都包含一个来自 self 的键值对。

Hash.to_h

如果是哈希,则返回 self;如果是 Hash 的子类,则返回包含来自 self 的条目的 Hash。

to_hash

返回 self

Hash.to_proc

返回一个将给定键映射到其值的过程。

转换键和值的方法

Hash.transform_keys

返回带有修改键的 self 的副本。

transform_keys!

修改 self 中的键

Hash.transform_values

返回带有修改值的 self 的副本。

Hash.transform_values!

修改 self 中的值。

其他方法

Hash.flatten

返回一个数组,它是 self 的一维展平。

Hash.invert

返回每个键值对反转的哈希。

相关用法


注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 Hash类。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。