Hash
公式サイト:
class Hash | Ruby リファレンスマニュアル [公式]
使い方
空のハッシュを作成する。
empty = {}
Code language: Ruby (ruby)
ハッシュを作成する。
user = { name: "John", age: 42, sex: :male }
Code language: Ruby (ruby)
ハッシュに値を格納する。
user[:full_name] = "John Smith"
Code language: Ruby (ruby)
参考:
select などの配列の抽出/検索を行うメソッドまとめ – Qiita
作成する
参考:
Hash.[] | Ruby リファレンスマニュアル [公式]
Hash.new | Ruby リファレンスマニュアル [公式]
Creating a hash key from a variable in Ruby? – Stack Overflow
キーから該当する値を取得する
[]
:キーが存在しなかった場合、生成時に指定されたデフォルト値を返す。生成時にデフォルト値を指定しなかった場合、nil
を返す。fetch
:キーが存在しなかった場合、デフォルト値を指定する引数が与えられていれば、その値を返す。もしくは、ブロックが与えられていれば、ブロックを評価して返す。引数もブロックもなければ、例外を投げる。
参考:
Hash#[] | Ruby リファレンスマニュアル [公式]
Hash#fetch | Ruby リファレンスマニュアル [公式]
デフォルト値
Hash.new
にブロックを与えると、ハッシュに存在しないキーが与えられる度にブロックを評価してその値を返す。ブロック内で該当のキーに値を設定すると各キーに対して一度だけ評価し、その後はハッシュに保存された値を取得できる。
h = Hash.new { |h, k| h[k] = "generated default value for #{k}" }
Code language: Ruby (ruby)
key? / has_key?
参考:
Hash#has_key? | Ruby リファレンスマニュアル [公式]
keys
参考:
ハッシュに含まれるキーや値を配列として取得 | Let’s プログラミング
Hash#keys | Ruby リファレンスマニュアル [公式]
values
参考:
Hash#values | Ruby リファレンスマニュアル [公式]
values_at
引数で与えられたキーに該当する値の配列を取得する。引数が指定されなかった場合は空の配列を返す。
{ a: 1, b: 2, c: 3 }.values_at(:a, :b)
# => [1, 2]
Code language: Ruby (ruby)
参考:
Hash#values_at | Ruby リファレンスマニュアル [公式]
to_a
Hash#to_a | Ruby リファレンスマニュアル [公式]
to_h
参考:
each_with_object も map も使わずに to_h だけで配列をハッシュに変換する | TechRacho
Array#to_h | Ruby リファレンスマニュアル [公式]
select / select!
参考:
Hash#filter | Ruby リファレンスマニュアル [公式]
Hash#keep_if | Ruby リファレンスマニュアル [公式]
each_with_object
delete_if
と each_with_object
を使って破壊的に抽出する。
source = { a: "hoge", b: "fuga", c: "piyo" }
extracted =
source.delete_if.each_with_object({}) do |(key, value), result|
next false unless %i[a b].include?(key)
result
= value
true
end
# => { a: "hoge", b: "fuga" }
source
# => { c: "piyo" }
Code language: Ruby (ruby)
参考:
inject と each_with_object って何が違うのさ? – Qiita
Enumerable#each_with_object | Ruby リファレンスマニュアル [公式]
map
hash.map { |k, v| [k, conv(v)] }.to_h
Code language: Ruby (ruby)
参考:
Hash に map で値を変換した Hash を作成する – Qiita
Enumerable#collect | Ruby リファレンスマニュアル [公式]
Changing every value in a hash in Ruby – Stack Overflow
transform_values / transform_values!
参考:
Hash#transform_values | Ruby リファレンスマニュアル [公式]
Hash#transform_values! | Ruby リファレンスマニュアル [公式]
transform_keys / transform_keys!
参考:
Hash#transform_keys | Ruby リファレンスマニュアル [公式]
Hash#transform_keys! | Ruby リファレンスマニュアル [公式]
ソート
key でソートする
昇順 (ASC)
sorted_hash = Hash[hash.sort]
Code language: Ruby (ruby)
降順 (DESC)
sorted_hash = Hash[hash.sort.reverse]
Code language: Ruby (ruby)
value でソートする
昇順 (ASC)
sorted_hash = Hash[hash.sort_by { |_, v| v }]
Code language: Ruby (ruby)
降順 (DESC)
sorted_hash = Hash[hash.sort_by { |_, v| -v }]
Code language: Ruby (ruby)
参考:
Hash を key / value で ASC / DESC ソート – Qiita
Enumerable#sort | Ruby リファレンスマニュアル [公式]
Enumerable#sort_by | Ruby リファレンスマニュアル [公式]
merge
参考:
Hash#merge | Ruby リファレンスマニュアル [公式]
merge! / update
引数に与えたハッシュのキーと値でハッシュを破壊的に更新 (マージ) する。
参考:
Hash#merge! | Ruby リファレンスマニュアル [公式]
splat merge
参考:
Hash の splat merge する時は 2.2 からにしといた方が無難 – GitHub Gist
Double Splat to Merge Hashes | The Pug Automatic
Splat Hash Values | Today I Learned
fetch
fetch
メソッドに引数 key
を指定するとそのキーの値を返す。キーが存在しないときは例外が発生する。ハッシュにデフォルト値が設定されていても例外が発生する。
hash.fetch(key)
Code language: Ruby (ruby)
第2引数 default
を指定すると、キーが存在しないときは default
を返す。
hash.fetch(key, default)
Code language: Ruby (ruby)
fetch
メソッドにブロックを渡すと、キーが存在しないときはブロックの戻り値を返す。ブロック引数 k
には引数 key
で指定したキーが入る。
hash.fetch(key) {|k| block }
Code language: Ruby (ruby)
参考:
Hash#fetch | Ruby リファレンスマニュアル [公式]
dig
参考:
Hash#dig | Ruby リファレンスマニュアル [公式]
ネストした Hash や Array から値を取り出す方法いろいろ – Qiita
深い階層の nil チェックまとめ try &. dig | DoRuby
delete
キーに対応する要素を削除する。
参考:
Hash#delete | Ruby リファレンスマニュアル [公式]
reject / reject! / delete_if
参考:
Hash#reject | Ruby リファレンスマニュアル [公式]
Hash#delete_if | Ruby リファレンスマニュアル [公式]
each / each_pair
each
あるいは each_pair
は、キーと値のペアを引数としてブロックを繰り返す。
foods = { Alice: "apples", Bob: "bananas" }
foods.each do |name, food|
puts "#{name} likes #{food}"
end
Code language: Ruby (ruby)
参考:
Hash#each | Ruby リファレンスマニュアル [公式]
reduce
参考:
inject メソッドを使いこなす | Hack Your Design!
Enumerable#inject | Ruby リファレンスマニュアル [公式]
Change (and update) values of hash | Ruby-Forum
How to change Hash values? – Stack Overflow
clear
ハッシュの内容を空にする。デフォルト値は維持される。
参考:
Hash#clear | Ruby リファレンスマニュアル [公式]
assoc / rassoc
参考:
Hash#assoc | Ruby リファレンスマニュアル [公式]
Hash#rassoc | Ruby リファレンスマニュアル [公式]
key
値を持つキーを返す。
hash.key(value)
Code language: Ruby (ruby)
参考:
Find a Hash Key Given it’s Value | makandra dev
Hash#index | Ruby リファレンスマニュアル [公式]
invert
参考:
Hash#invert | Ruby リファレンスマニュアル [公式]
逆順に格納する (reverse)
逆順に格納したハッシュを作成するには、to_a
で配列に変換して逆順に並べ替えた後に、ハッシュに戻す。
reversed_hash = Hash[hash.to_a.reverse]
Code language: Ruby (ruby)
または、ハッシュに戻す際に to_h
を適用する。
reversed_hash = hash.to_a.reverse.to_h
Code language: Ruby (ruby)
または、reverse_each
を用いて to_h
を適用する。
reversed_hash = hash.reverse_each.to_h
Code language: Ruby (ruby)
参考:
Array#reverse | Ruby リファレンスマニュアル [公式]
Enumerable#reverse_each | Ruby リファレンスマニュアル [公式]
Reverse a hash in Ruby – Stack Overflow
比較する
ハッシュにおける ==
メソッドを使った比較は、キーが eql?
メソッドで等しく、値が ==
メソッドで比較して全て等しい場合に真を返す。
参考:
Array と Hash は == で中身の比較を行う | ぺけみさお
Hash#== | Ruby リファレンスマニュアル [公式]
String#eql? | Ruby リファレンスマニュアル [公式]
deep_diff
ネストしたハッシュの差分を取る。
# deep_diff for Hash (v1.0.0)
Hash.class_eval do
def deep_diff(b)
a = self
(a.keys | b.keys).each_with_object({}) do |k, diff|
next if a[k] == b[k]
diff[k] =
if a[k].respond_to?(:deep_diff) \
&& b[k].respond_to?(:deep_diff) then
a[k].deep_diff(b[k])
else
[a[k], b[k]]
end
end
end
def self.deep_diff(a, b)
if a.is_a?(Array) && b.is_a?(Array) \
&& a.length == b.length then
a.zip(b).each_with_object([]) do |(x, y), inside|
inside << deep_diff(x, y)
end.yield_self do |diff|
diff.all?(&:nil?) ? nil : diff
end
elsif a.is_a?(Hash) && b.is_a?(Hash) then
(a.keys | b.keys).each_with_object({}) do |k, diff|
next if a[k] == b[k]
diff[k] = deep_diff(a[k], b[k])
end.yield_self do |diff|
diff.empty? ? nil : diff
end
else
[a, b]
end
end
end
Code language: Ruby (ruby)
実行テスト
a = { a: { x: 1, y: 2 }, b: { x: 3, y: 4 } }
b = { a: { x: 5 }, b: { x: 6 } }
p a.deep_diff(b)
# => {:a=>{:x=>[1, 5], :y=>[2, nil]}, :b=>{:x=>[3, 6], :y=>[4, nil]}}
p Hash.deep_diff(a, b)
# => {:a=>{:x=>[1, 5], :y=>[2, nil]}, :b=>{:x=>[3, 6], :y=>[4, nil]}}
x = [{ a: 1, b: 2 }, { c: 3, d: 4 }]
y = [{ a: 5 }, { c: 6 }]
p Hash.deep_diff(x, y)
# => [{:a=>[1, 5], :b=>[2, nil]}, {:c=>[3, 6], :d=>[4, nil]}]
p Hash.deep_diff([{ a: 1 }, { b: 2 }], [{ a: 1 }, { b: 2 }])
# => nil
p Hash.deep_diff([1, 2, 3], [4, 5, 6])
# => [[1, 4], [2, 5], [3, 6]]
p Hash.deep_diff([1, 2, 3], [4, 5])
# => [[1, 2, 3], [4, 5]]
Code language: Ruby (ruby)
コード:
Recursively Diff Two Hashes (henrik) – GitHub Gist
参考:
How do I compare two hashes? – Stack Overflow
Comparing ruby hashes – Stack Overflow
キーの一致
参考:
Hash#compare_by_identity | Ruby リファレンスマニュアル [公式]
Hash#compare_by_identity? | Ruby リファレンスマニュアル [公式]
method_missing
参考:
ハッシュにメソッドでアクセスするには?やらない方がいい? | ザリガニが見ていた…。
ハッシュを構造体のように使う | m-kawato@hatena_diary
シンボル値
to_sym
:文字列をシンボル値に変換するto_s
:シンボル値を文字列に変換する
参考:
Hash のキーを文字列からシンボルに変換する – Qiita
Hash クラスにおけるキーの書きかたいろいろ – Qiita
to_sym を使わずに文字列からシンボルを生成 | そういうこともある
文字列からシンボルへの変換 String#intern の命名の由来 – Qiita
String#intern | Ruby リファレンスマニュアル [公式]
Symbol#id2name | Ruby リファレンスマニュアル [公式]
Hash を扱うときに string と symbol どちらを key にするか – teratail
デバッグ/ダンプ (inspect)
参考:
Hash#inspect | Ruby リファレンスマニュアル [公式]
Tips
便利な組み込みクラスのメソッド達 Hash 編 – Qiita
Ruby の Hash 入門 | 酒と涙とRubyとRailsと
Ruby における Hash 操作の逆引きまとめ | tech-dig
Hash Tricks in Ruby | ThirtySixthSpan
ActiveSupport による拡張 (Ruby on Rails)
参考:
ActiveSupport の Hash 拡張である slice / except がびっくりするぐらい便利 – Qiita
Rails で Hash の一部だけを取り出す/取り除く方法 – Qiita
ちょっと便利な ActiveSupport の標準クラス拡張 Array & Hash 編 | おどるダメ人間
Hash | Ruby on Rails API [Official]
ActiveSupport::HashWithIndifferentAccess | Ruby on Rails API [Official]
slice / slice!
参考:
slice – Hash | Ruby on Rails API [Official]
slice! – Hash | Ruby on Rails API [Official]
except / except!
参考:
except – Hash | Ruby on Rails API [Official]
except! – Hash | Ruby on Rails API [Official]
extract!
参考:
extract! – Hash | Ruby on Rails API [Official]
symbolize_keys / symbolize_keys!
参考:
symbolize_keys – Hash | Ruby on Rails API [Official]
symbolize_keys! – Hash | Ruby on Rails API [Official]
deep_symbolize_keys / deep_symbolize_keys!
参考:
deep_symbolize_keys – Hash | Ruby on Rails API [Official]
deep_symbolize_keys! – Hash | Ruby on Rails API [Official]
with_indifferent_access
参考:
with_indifferent_access – Hash | Ruby on Rails API [Official]
deep_merge / deep_merge!
参考:
階層の深い Hash の merge (deep_merge) と、そのコード簡略化 – Qiita
Hash の deep_merge で Hash 内部にある Array も連結する – Qiita
Hash.deep_merge – 欲しかったので作ってみた深い統合 | 自分の歩いた道に落ちてるコード
deep_merge – Hash | Ruby on Rails API [Official]
deep_merge! – Hash | Ruby on Rails API [Official]
merge nested hash – Stack Overflow
ActiveSupport::OrderedOptions
メソッドで要素にアクセスできるよう拡張された Hash
の派生クラス
参考:
ActiveSupport::OrderedOptions | Ruby on Rails API [Official]
コード:
rails/ordered_options.rb at v7.0.0 · rails/rails – GitHub
ActiveSupport::InheritableOptions
Hash
あるいは OrderedOptions
から値を継承した OrderedOptions
を作成するためのクラス。継承したハッシュは作成した InheritableOptions
の初期値として与えられる。
参考:
ActiveSupport::InheritableOptions | Ruby on Rails API [Official]
ActiveSupport::OrderedHash
**DEPRECATED**
ドキュメント:
ActiveSupport::OrderedHash | Ruby on Rails 6.1.0 API [Official]
コード:
ordered_hash.rb at v6.1.6 · rails/rails – GitHub
Hashdiff
リポジトリ:
ドキュメント:
Documentation – hashdiff | RubyDoc.info
hash_diff
リポジトリ:
CodingZeal/hash_diff: Diff Tool for Deep Ruby Hash Comparison – GitHub
Deep Merge
リポジトリ:
danielsdeleo/deep_merge: Recursive Merging for Ruby Hashes – GitHub