4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Hashの探査(dig)実装メモ

Last updated at Posted at 2015-06-19

ネストされたHashをどんどん掘っていく、探査するメソッドが欲しいです。
が、Ruby 2.3からHash#digメソッドが追加されたので本記事は意味を成しません。
Ruby 2.2以前の時に参考になるレベルです。

# Hash掘るよ
# @param [Hash] data 対象のHash
# @param [Array] keys dataを掘っていくためのキー
# @return [Anything] 掘っていった結果
def dig(data, keys)
  return data unless data.is_a?(Hash)
  key = keys.shift
  return data unless key
  dig(data[key], keys)
end

data = {fuga: {bar: {piyo: 'good'}}}
p hoge(data, [:fuga, :bar, :piyo]) #=> 'good'
p hoge(data, [:fuga, :bar]) #=> {piyo: 'good'}
p hoge(data, [:fuga, :baz]) #=> nil

こんなの書いて使ってたけど、なんかダサい気がしてならない。
何かスマートな方法ないかと探してたらこんなものがありました。
ruby hash dig
転載させていただきますが、なにか問題あったら消しますので連絡ください。
Please contact me if there is a problem.

class Hash
 
  def dig(*path)
    path.inject(self) do |location, key|
      location.is_a?(Hash) ? location[key] : nil
    end
  end
 
end

なるほど、injectの初期値に対象のデータをセットする発想はなかった!
injectはいつも空ハッシュにデータを突っ込んでいく使い方しかしていなかったので、このような使い方があるとは眼から鱗です。

でも個人的にオープンクラスが好きではないのと、デフォルト値を返すみたいなことができると嬉しいな、と思って改変しました。

# Hash形式のデータを掘る
# @param [Hash] data 掘る対象のデータ
# @param [Array] keys 掘りたいキー群
# @param [Anything] defalut キーがない場合、dataがHashじゃなくなった場合の返り値
# @return [Anything] 末端まで掘った値
def dig(data, keys, default={})
  keys.inject(data) do |location, key|
    (location.is_a?(Hash) && location[key]) ? location[key] : default
  end
end

dig(data, [:fuga, :bar, :piyo]) #=> 'good'
dig(data, [:fuga, :bar]) #=> {piyo: 'good'}
dig(data, [:fuga, :baz]) #=> {}
dig(data, [:fuga, :baz], 'default') #=> 'default'

悪くないですね(自己満足)

結局、今回もこのメソッドを実装した後に仕様が変わって不要になりましたが、今後どこかで使うことも出てくると思ったのでQiitaに残しておきます。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?