Hash

参考:

class Hash (Ruby 2.6.0)

使い方

参考:

select などの配列の抽出・検索を行うメソッドまとめ – Qiita

Ruby における hash 操作の逆引きまとめ | tech-dig

繰り返しの Hash を楽に書きたかった – Qiita

Ruby の hash 宣言方法いろいろ – Qiita

Ruby Hash についてまとめる – Qiita

ハッシュの作成

参考:

singleton method Hash.[] (Ruby 2.6.0)

singleton method Hash.new (Ruby 2.6.0)

Creating a hash key from a variable in Ruby? – Stack Overflow

デフォルト値

Hash.new にブロックを与えると、ハッシュに存在しないキーが与えられる度にブロックを評価してその値を返す。ブロック内で該当のキーに値を設定すると各キーに対して一度だけ評価し、その後はハッシュに保存された値を取得できる。

h = Hash.new { |h, k| h[k] = "generated default value for #{k}" }

key? / has_key?

参考:

instance method Hash#has_key? (Ruby 2.6.0)

keys

instance method Hash#keys (Ruby 2.6.0)

keys (Hash) | Ruby リファレンス (ref.xaio.jp)

Hash の先頭キー取得方法 | teratail

values

参考:

instance method Hash#values (Ruby 2.6.0)

values (Hash) | Ruby リファレンス (ref.xaio.jp)

values_at

引数で与えられたキーに該当する値の配列を取得する。引数が指定されなかった場合は空の配列を返す。

{ a: 1, b: 2, c: 3 }.values_at(:a, :b)
# => [1, 2]

参考:

instance method Hash#values_at (Ruby 2.6.0)

to_a

instance method Hash#to_a (Ruby 2.6.0)

to_a (Hash) | Ruby リファレンス (ref.xaio.jp)

to_h

参考:

each_with_object も map も使わずに to_h だけで配列をハッシュに変換する | TechRacho

instance method Array#to_h (Ruby 2.6.0)

select / select!

参考:

instance method Hash#filter (Ruby 2.6.0)

instance method Hash#keep_if (Ruby 2.6.0)

each_with_object

delete_ifeach_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[key] = value
    true
  end
# => { a: "hoge", b: "fuga" }

source
# => { c: "piyo" }

参考:

inject と each_with_object って何が違うのさ? – Qiita

instance method Enumerable#each_with_object (Ruby 2.6.0)

map

hash.map { |k, v| [k, conv(v)] }.to_h

参考:

Hash#map は Hash を返さない – Qiita

Hash に map で値を変換した Hash を作成する – Qiita

instance method Enumerable#collect (Ruby 2.6.0)

Changing every value in a hash in Ruby – Stack Overflow

transform_values / transform_values!

参考:

instance method Hash#transform_values (Ruby 2.6.0)

instance method Hash#transform_values! (Ruby 2.6.0)

transform_keys / transform_keys!

参考:

instance method Hash#transform_keys (Ruby 2.6.0)

instance method Hash#transform_keys! (Ruby 2.6.0)

ソート

key でソートする

ASC 昇順

sorted_hash = Hash[hash.sort]

DESC 降順

sorted_hash = Hash[hash.sort.reverse]

value でソートする

ASC 昇順

sorted_hash = Hash[hash.sort_by { |_, v| v }]

DESC 降順

sorted_hash = Hash[hash.sort_by { |_, v| -v }]

参考:

Hash を key / value で ASC / DESC ソート – Qiita

instance method Hash#sort (Ruby 2.6.0)

instance method Enumerable#sort_by (Ruby 2.6.0)

merge

参考:

instance method Hash#merge (Ruby 2.6.0)

merge, merge! (Hash) | Ruby リファレンス (ref.xaio.jp)

merge! / update

引数に与えたハッシュのキーと値でハッシュを破壊的に更新 (マージ) する。

参考:

instance method Hash#merge! (Ruby 2.6.0)

splat merge

参考:

ruby で hash の splat merge (っていうのか知らないけど) する時は 2.2 からにしといた方が無難 – GitHub Gist

Double splat to merge hashes | The Pug Automatic

Splat hash values in ruby | Today I Learned

fetch

fetch メソッドに引数 key を指定するとそのキーの値を返す。キーが存在しないときは例外が発生する。ハッシュにデフォルト値が設定されていても例外が発生する。

hash.fetch(key)

第2引数 default を指定すると、キーが存在しないときは default を返す。

hash.fetch(key, default)

fetch メソッドにブロックを渡すと、キーが存在しないときはブロックの戻り値を返す。ブロック引数 k には引数 key で指定したキーが入る。

hash.fetch(key) {|k| block }

参考:

instance method Hash#fetch (Ruby 2.6.0)

fetch (Hash) | Ruby リファレンス (ref.xaio.jp)

dig

参考:

instance method Hash#dig (Ruby 2.6.0)

Ruby でネストした Hash や Array から値を取り出す方法いろいろ – Qiita

深い階層の nil チェックまとめ try &. dig | DoRuby

delete

キーに対応する要素を削除する。

参考:

instance method Hash#delete (Ruby 2.6.0)

reject / reject! / delete_if

参考:

instance method Hash#reject (Ruby 2.6.0)

instance method Hash#delete_if (Ruby 2.6.0)

each / each_pair

参考:

ハッシュに対する繰り返し | Ruby入門

instance method Hash#each (Ruby 2.6.0)

each, each_pair (Hash) | Ruby リファレンス (ref.xaio.jp)

reduce

参考:

Ruby の inject メソッドを使いこなす | Hack Your Design!

instance method Enumerable#inject (Ruby 2.6.0)

Change (and update) values of hash | Ruby-Forum

How to change Hash values? – Stack Overflow

clear

ハッシュの内容を空にする。デフォルト値は維持される。

参考:

instance method Hash#clear (Ruby 2.6.0)

assoc / rassoc

参考:

instance method Hash#assoc (Ruby 2.6.0)

instance method Hash#rassoc (Ruby 2.6.0)

key

値を持つキーを返す。

hash.key(value)

参考:

Find a hash key given it’s value | makandra dev

instance method Hash#index (Ruby 2.6.0)

invert

参考:

instance method Hash#invert (Ruby 2.6.0)

Hash に reverse を適用する方法

reversed_hash = Hash[hash.to_a.reverse]

reversed_hash = hash.to_a.reverse.to_h

reversed_hash = hash.reverse_each.to_h

参考:

instance method Array#reverse (Ruby 2.6.0)

instance method Enumerable#reverse_each (Ruby 2.6.0)

Reverse a hash in Ruby – Stack Overflow

ハッシュを比較する

ハッシュにおける == メソッドを使った比較は、キーが eql? メソッドで等しく、値が == メソッドで比較して全て等しい場合に真を返す。

参考:

Ruby の Array と Hash は == で中身の比較を行う | ぺけみさお

instance method Hash#== (Ruby 2.6.0)

instance method String#eql? (Ruby 2.6.0)

deep_diff

ネストしたハッシュの差分を取る。

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

実行テスト

a = { a: { x: 1, y: 2 }, b: { x: 3, y: 4 } }
b = { a: { x: 5 }, b: { x: 6 } }
a.deep_diff(b)
# => {:a=>{:x=>[1, 5], :y=>[2, nil]}, :b=>{:x=>[3, 6], :y=>[4, nil]}}
Hash.deep_diff(a, b)
# => {:a=>{:x=>[1, 5], :y=>[2, nil]}, :b=>{:x=>[3, 6], :y=>[4, nil]}}

p = [{ a: 1, b: 2 }, { c: 3, d: 4 }]
q = [{ a: 5 }, { c: 6 }]
Hash.deep_diff(p, q)
# => [{:a=>[1, 5], :b=>[2, nil]}, {:c=>[3, 6], :d=>[4, nil]}]

Hash.deep_diff([{ a: 1 }, { b: 2 }], [{ a: 1 }, { b: 2 }])
# => nil

Hash.deep_diff([1, 2, 3], [4, 5, 6])
# => [[1, 4], [2, 5], [3, 6]]
Hash.deep_diff([1, 2, 3], [4, 5])
# => [[1, 2, 3], [4, 5]]

参考:

Recursively diff two Ruby hashes – GitHub Gist

How do I compare two hashes? – Stack Overflow

Comparing ruby hashes – Stack Overflow

キーの一致

参考:

instance method Hash#compare_by_identity (Ruby 2.6.0)

instance method Hash#compare_by_identity? (Ruby 2.6.0)

method_missing

参考:

Ruby のハッシュにメソッドでアクセスするには?やらない方がいい? | ザリガニが見ていた…。

ハッシュを構造体のように使う | m-kawato@hatena_diary

Tips

参考:

ハッシュの便利メソッドあれこれ – Qiita

便利な組み込みクラスのメソッド達 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!

参考:

ハッシュから特定のキーのハッシュを作る – Qiita

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 の deep_merge で Hash 内部にある Array も連結する – Qiita

欲しかったので作ってみた Ruby の 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 v5.2.3 · rails/rails – GitHub

ActiveSupport::InheritableOptions

Hash あるいは OrderedOptions から値を継承した OrderedOptions を作成するためのクラス。継承したハッシュは作成した InheritableOptions の初期値として与えられる。

参考:

ActiveSupport::InheritableOptions | Ruby on Rails API [Official]

ActiveSupport::OrderedHash

***DEPRECATED***

参考:

ActiveSupport::OrderedHash | Ruby on Rails API [Official]

rails/ordered_hash.rb at v5.2.3 · rails/rails – GitHub

Hashdiff

参考:

liufengyun/hashdiff: HashDiff is a ruby library to to compute the smallest difference between two hashes – GitHub

Documentation for hashdiff | RubyDoc.info

hash_diff

参考:

CodingZeal/hash_diff: Diff tool for deep Ruby hash comparison – GitHub

タグ:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です