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)

参考:

Hash についてまとめる – Qiita

Hash 操作の逆引きまとめ | tech-dig

Hash 宣言方法いろいろ – Qiita

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

繰り返しの Hash を楽に書きたかった – 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 リファレンスマニュアル [公式]

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

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_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 = 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

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)

参考:

ハッシュに対する繰り返し | 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

ハッシュの便利メソッドあれこれ – 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 の 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

リポジトリ:

liufengyun/hashdiff: HashDiff is a Ruby Library to Compute the Smallest Difference between Two Hashes – GitHub

ドキュメント:

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

記事をシェアする:
タグ:

コメントを残す

メールアドレスが公開されることはありません。

Protected by reCAPTCHA