1. ホーム
  2. ruby

[解決済み] Ruby - 多次元ハッシュへのアクセスとnilオブジェクトへのアクセス回避 [duplicate]

2023-04-04 23:53:53

質問

重複の可能性があります。

ルビー IF文の中のNils

ネストされたパラメータハッシュのnilでメソッドを呼び出すことを避けるためのきれいな方法はありますか?

このようなハッシュにアクセスしようとするとします。

my_hash['key1']['key2']['key3']

key1、key2、key3がハッシュ内に存在する場合は良いのですが、例えばkey1が存在しない場合はどうでしょうか?

その場合、私は NoMethodError: undefined method [] for nil:NilClass . そして誰もそれを好まない。

今までは、このように条件をつけて対処していました。

if my_hash['key1'] && my_hash['key1']['key2'] ...

これは適切なのでしょうか、他にRubiestな方法はないのでしょうか?

どのように解決するのですか?

いろいろなアプローチがあります。

Ruby2.3以降を使用している場合は ディグ

my_hash.dig('key1', 'key2', 'key3')

多くの人は、プレーンなルビーにこだわり、ルビーにチェーンして && ガードテストを連鎖させます。

stdlib を使うことができる ハッシュ#フェッチ も使えます。

my_hash.fetch('key1', {}).fetch('key2', {}).fetch('key3', nil)

ActiveSupport の #try メソッドを連鎖させるようなものもあります。

my_hash.try(:[], 'key1').try(:[], 'key2').try(:[], 'key3')

その他は

myhash['key1'].andand['key2'].andand['key3']

ある人は 自己中心的なニルス は良いアイデアだと思う人もいます (ただし、これをやっているのを見つけたら、誰かに追い詰められて拷問されるかもしれません)。

class NilClass
  def method_missing(*args); nil; end
end

my_hash['key1']['key2']['key3']

を使うことができます。 Enumerable#reduce (またはaliases inject)を使ってください。

['key1','key2','key3'].reduce(my_hash) {|m,k| m && m[k] }

あるいは、Hashを拡張するか、ネストされたルックアップ・メソッドを持つターゲット・ハッシュ・オブジェクトだけを拡張することもできます。

module NestedHashLookup
  def nest *keys
    keys.reduce(self) {|m,k| m && m[k] }
  end
end

my_hash.extend(NestedHashLookup)
my_hash.nest 'key1', 'key2', 'key3'

ああ、それから、どうして もしかしたら モナドを忘れてはいけません。

Maybe.new(my_hash)['key1']['key2']['key3']