2017-01-20 6 views
1

ハッシュ内の単純なハッシュでキー/値の問題を解決しようとしています。Rubyハッシュは、私が知っているキーの値としてnilを返しています。

私の鍵は私のコードで使用されるAPIから来ているタイプ「OpenStudio :: OptionalString」は次のとおりです。デバッグモードでは、私はハッシュを検査し、最初の行が正しくキーを入力したことを見た

#---NOTE---: key here is of type OpenStudio::OptionalString 

my_hash[key]['heating_plant_system'] = 'Boiler' 
my_value = my_hash[key]['heating_plant_system'] #returning nil 

/2行目を実行すると値を取得できません。 my_valueはnilを返します。私はそれがこの奇妙なキータイプに起因することを知っていますが、私はそれを変更する自由がありません。

私のハッシュからこの値にアクセスしようとしたときに間違ったことをしていますか?


一般的なことを維持しようとすると、あまりにも多くの文脈を犠牲にしたかもしれません。

require 'openstudio' 

model = OpenStudio::Model::Model.new 
my_zone = OpenStudio::Model::ThermalZone.new(model) 

my_zone.setName('Zone 1') 

zone_hash = Hash.new { |h, k| h[k] = { } } 

zone_hash[my_zone.name]['heating_plant'] = 'Boiler' 

puts "my zone's name is #{my_zone.name}" #Output: 'my zone's name is Zone 1' 
puts zone_hash.to_s #Output: {#<OpenStudio::OptionalString:0x5fa4980 @__swigtype__="_p_boost__optionalT_std__string_t">=>{"heating_plant"=>"Boiler"}} 

if zone_hash[my_zone.name]['heating_plant'].nil? 
    puts 'Im unable to access this hash, help!' #<--- this is executed 
else 
    puts "I am able to access #{zone_hash[my_zone.name]['heating_plant']}" 
end 

私は(簡単に)このzone_hashがOpenStudio :: OptionalString以外にキーを変更することで、私の実際のコードベースで働いていた方法を元に戻すことができませんでしたので、私はこのループを使用:これは完全な例であります回避策としてそれはきれいではありませんが、それは仕事は私が行うために必要な細かいチェックのために行われました:

zones_hash.each {|k,v| 
    if zone.name.to_s == k.to_s 
    v.each {|k1,v1| 
     if k1 == 'heating_plant' 
     heating_plant = v1.to_s 
     end 
    } 
    end 
} 
+0

どのようなタイプの 'my_hash [キー]'ですか? – coreyward

+3

'my_hash [key] .keys'の出力を表示できますか? –

+0

より詳細な例はありません。私は、あなたが[dig](http://stackoverflow.com/questions/41753945/ruby-hash-returning-nil-for-value-for-a- key-i-know-exists)メソッドを呼び出します。 – OneNeptune

答えて

4

ルビーでは、hasheql?を使用して、ハッシュキーの同等性をチェックします。

OpenStudio::OptionalStringのように見えるものが正しく実装されていない可能性があります。その場合、あなたの最善の解決策は別の鍵を使用することです。

Rubyは、2つのオブジェクトが同じキーと見なされる場合、同じhashの値を返す必要がありますが、同じハッシュ値を持つということは同じキーであるとは限りません。これらのケースを解決するには、eql?メソッドを内部的に使用します。

OpenStudio::OptionalStringクラスのhasheql?メソッドを修正することもできますが、そのライブラリは内部的に「壊れた」動作に依存している可能性があります。そのため、たとえば、これらのオブジェクトの文字列表現のような別のハッシュキーを使用することをお勧めします。

-1

ハッシュキーは限りオブジェクトは一意であるとして任意のオブジェクトタイプにすることができます。一意性または等価性の定義は、 "Hash Keys"にあります。この上

瞑想:

v1 = %w(a b) 
v2 = %w(c d) 
hash = {v1 => 1, v2 => 2} 
hash # => {["a", "b"]=>1, ["c", "d"]=>2} 
hash[v1] # => 1 
hash[%w(a b)] # => 1 

キーがユニークである限り、あなたはそれを使用することができます。でも

class Foo 
end 

foo1 = Foo.new 
foo2 = Foo.new 

foo1.hash # => 1202274030892197226 
foo2.hash # => 2774925608615277787 

hash = {foo1 => 1, foo2 => 2} 
hash[foo1] # => 1 

または:

class Foo 
    def initialize 
    @init_time = Time.now 
    end 

    def init_time 
    @init_time 
    end 
end 

foo1 = Foo.new 
foo2 = Foo.new 

foo1.init_time.to_f # => 1484874655.324574 
foo2.init_time.to_f # => 1484874655.324577 

hash = {foo1.init_time => 1, foo2.init_time => 2} 
hash[foo1.init_time] # => 1 

ありませんかなり真実なyはハッシュとeqlを使用しますか?ハッシュの平等のために、デフォルト実装がobject_idに依存しているだけです。

あなたが正しいと思っていたのは間違いありませんでした。 the docsから:そのhash値が同一である場合

2つのオブジェクトが同じハッシュキーを参照し、2つのオブジェクトが互いにeql?です。

+0

Rubyはハッシュ等価性のために 'hash'と' eql? 'を使用していますが、デフォルトの実装は' object_id'に依存します。 – akuhn

+0

@akuhn実装は 'object_id'に依存しないことがあります。このことを考慮。 'arr = [1];ハッシュ= {};ハッシュ[arr] = 1; arr << 2;ハッシュ[arr]#=> nil'。しかし、arrはまだすべて同じオブジェクトです –

+0

配列はデフォルト実装を使用しません。ストリングもそうではありません。それはまさに私が言っていることです、ハッシュキーは「ユニーク」なものではなく、 'hash'と' eql? 'で定義されたアイデンティティを使います。 – akuhn

関連する問題