跳至主要内容

[Ruby] Hash

在 Ruby 中的 Hash 就類似 JavaScript 中的 Object,是 key-value pairs。

# hash with default value
my_hash = Hash.new([default_value]) # Hash.new constructor

# a hash with default hash
my_default_hash = Hash.new{ |h, k| h[k] = { video_counts: 0, device_counts: 0 } }

my_hash = {} # Hash literal notation

Ruby Documentation @ 官方

目錄

[TOC]

建立雜湊 Hash

######################################
## 雜湊建立 ##
######################################

# 建立空 hash
item = Hash.new # {} hash constructor notation
item = Hash.new(0) # 建立帶有預設值的 Hash
item = {} # {} hash literal notation


# 建立帶有預設值的 Hash
item = Hash.new('這裡放預設值')
puts new_hash # {}
puts new_hash['abc'] # {abc => 這裡放預設值}

# 建立帶值的 hash
receipt = {"item" => "apple", "quantity" => 1}
receipt = {:item => "apple", :quantity => 1} # hash 的 key 可以是其他資料型態,最常用的是 symbol
receipt = {item: "apple", quantity: 1} # 如果你的 key 是 symbol,那麼可以縮寫成這樣

取用雜湊

receipt["item"]

######################################
## 疊代雜湊 ##
######################################
hash.each do |key,value|
puts "KEY:#{key}, VALUE: #{value}"
end

使用 dig() 來取用雜湊

keywords: Hash.dig()

使用 dig() 可以避免當 Hash 中的內容不存在時

hash = {
image: {
'1x': 'v6/customer_brands/openstack.png',
'2x': 'v6/customer_brands/openstack@2x.png'
}
}

hash.dig(:image, :'1x') # 'v6/customer_brands/openstack.png',
hash.dig(:image, :foo, :bar) # nil

hash[:image][:'1x'] # "v6/customer_brands/openstack.png"
hash[:image][:'foo'][:'bar'] # NoMethodError: undefined method `[]' for nil:NilClass

建值、取值、檢測值

######################################
## 雜湊操作 ##
######################################

# 增加 hash 的鍵值
receipt[:price] = 300 # {:item=>"apple", :quantity=>1, :price=>300}
receipt.store(:price, 300) # {:item=>"apple", :quantity=>1, :price=>300}

# hash 對於鍵的操作方法
hash.keys # 取得 hash 所有的 key,[:item, :quantity, :price]
hash.has_key?("brand") # 檢驗是否包含某一 key
hash.key?("brand") # 檢驗是否包含某一 key
hash.member?("brand") # 檢驗是否包含某一 key
hash.each_key{|key|} # 疊代所有的 key

# hash 對於值的操作方法
hash.values # 取得 hash 所有的 value,["apple", 1, 400]
hash.has_value?(400) # 檢驗是否包含某一 value
hash.value?("apple") # 檢驗是否包含某一 value
hash.values_at(:item, :price) # 顯示對應該鍵的值
hash.each_value{|v|} # 疊代所有的 value

# 其他方法(不會改變原 hash)
hash.length # 回傳鍵值配對數
hash.invert # 鍵值互換後回傳
hash.merge # 將兩個 hash 合併後回傳,如果兩個 hash 有相同的鍵,則以 merge 中的為主
hash.sort_by {|k, v| v} # 根據 Hash 的 Value 排序
hash.select{|k, v| v > 10} # 篩選 filter hash 中的內容
hash.each{|k, v|} # 疊代 hash


# 其他方法(會改變原 hash)
hash.shift # 刪除第一個鍵值對(會改變原 hash)
hash.reverse! # 改變(反轉)hash 中的排序
hash.delete(<key>) # 刪除 hash 中的某一個key-value pair

# 參數中代入 hash
puts(a: "A",b: "B") # {:a=>"A", :b=>"B"}
puts({:a => "A", :b => "B"}) # {:a=>"A", :b=>"B"}

# 建立 Hash 的預設值
my_hash = Hash.new([default_value])
my_default_hash = Hash.new{ |h, k| h[k] = { foo: 0, bar: 0 } }

Ruby Hash Default Behavior @ StackOverflow

常用方法

hash.merge()

# 類似 JavaScript 中的 {...obj, {foo: 'bar'}}
obj = {
a: 'a',
b: 'b'
}

obj_merge = {
a: 'aaa',
c: 'c'
}

obj.merge(obj_merge) # {a: "aaa", b: "b", c: "c"}

hash.sort_by{ |key, value| }

# 根據 hash 的 value 排序
hash.sort_by do |key, value|
value
end

hash.select{ |key, value| }

good_movies = movie_ratings.select { |k, v| v > 3 }

hash.each_with_index {|(key, value) , index|}

ticket = {"86138dda-2b1b-4cb1-8d51-05bedb77bc78"=>"2", "72b5f8f3-951b-4121-8c6a-ed8f7d711fff"=>"1"}

data = []

ticket.each_with_index do |(ticket_id, quantity), index|
data.push([ "autopick[#{index}]['size']", quantity ])
data.push([ "autopick[#{index}]['category']", ticket_id ])
end

puts data

其他小技巧

將雜湊根據值排序

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|_key, value| value}.to_h
# ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}

計算某字出現的次數

puts 'Whatever sentence you want to enter'
text = gets.chomp
words = text.split

frequencies = Hash.new(0)
words.each do |item|
frequencies[item] += 1
end

frequencies = frequencies.sort_by do |key, count|
count
end

frequencies.reverse!

frequencies.each do |word, count|
puts word + " " + count.to_s
end

參考資料