Edited at

Ruby で多次元ハッシュのキーの存在判定ってどうやんの?

More than 1 year has passed since last update.

今さら Ruby を覚え始めたのだが、多次元ハッシュのキーの存在判定はどうやるんだろう。


test.rb

#!/usr/bin/env ruby

h = { 'foo' => {} }

puts defined?(h['foo']['bar']) ? 'true' : 'false' # ==> true
puts h['foo']['bar']['baz'].present? # raise undefined method `[]' for nil:NilClass (NoMethodError)



test.pl

#!/usr/bin/env perl

use 5.010;
use strict;
use warnings;

my $h = { 'foo' => {} };

say defined $h->{'foo'}->{'bar'}->{'baz'} ? 'true' : 'false'; # ==> false


うーん、なんか本買って勉強したほうが良さそう…。


自己レス

Hash#dig で解決した。


test2.rb

#!/usr/bin/env ruby

h = { 'foo' => {} }

puts h.dig(*%w/foo bar baz/) # ==> nil


2.3 の新機能らしいけど、これがないときはどうやって生活してたの…。俺が Perl 脳過ぎるのか。


自己レス2

やりたかったことは Hash#dig で解決したのだが、厳密には Hash#dig ではキーの

存在判定にはならない(キーがあって値が nil な場合には nil が返ってきてしまう)と

ご指摘を受けて、@asm さんの下記実装案を採用しました。

require 'pp'

using Module.new {
refine NilClass do
def [] *arg
nil
end
def has_key?(key)
false
end
end
}

h = {}

pp h[:foo][:bar][:baz] # ==> nil
pp h[:foo][:bar].has_key?(:baz) # ==> false

かっこいい…かっこよくない?