我疯狂地试图解决哈希中的简单哈希上的键/值问题。
我的密钥是" OpenStudio :: OptionalString"它来自我的代码中使用的API:
#---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
在调试模式下,我检查了哈希并看到第一行正确输入了键/值输入,但是当我运行第二行时,我无法检索该值。 my_value
将返回零。我知道这是由于这种奇怪的密钥类型,但我无权改变它。
尝试从哈希中访问此值时,我是否犯了一个愚蠢的错误?
为了保持一般性,我可能牺牲了太多的背景。这是一个完整的例子:
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 :(得分:4)
Ruby使用hash
和eql?
来检查哈希键的相等性。
看起来OpenStudio::OptionalString
可能无法正确实现这些。如果是这种情况,您的最佳解决方案是使用另一个密钥。
Ruby对散列键做出以下假设 - 如果要将两个对象视为相同的键,则它们必须返回相同的hash
值,但是具有相同的散列值并不意味着它们是相同的键。方法eql?
在内部用于解决这些问题。
您还可以修复hash
类上的eql?
和OpenStudio::OptionalString
方法,但也许该库在内部依赖于“损坏”行为。这就是为什么我建议只使用另一个哈希键,例如这些对象的字符串表示。
答案 1 :(得分:-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
不完全正确,Ruby使用hash和eql?对于哈希等式,它恰好是默认实现依赖于object_id
你是对的,已经有很长一段时间了,因为我很清楚为什么它们是独一无二的。来自the docs:
当两个对象的
hash
值相同且两个对象彼此为eql?
时,它们引用相同的哈希键。