當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


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類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。