这是我的哈希:
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
我需要像以下方法一样访问哈希键:
tempData.a #100
tempData.here # 200
答案 0 :(得分:86)
您可以在OpenStruct中包装哈希:
require 'ostruct'
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
os = OpenStruct.new tempData
os.a #=> 100
os.here #=> 200
如果你真的很想,你也可以修补Hash
课程,但我建议不要这样做:
class Hash
def method_missing(m, *args, &blk)
fetch(m) { fetch(m.to_s) { super } }
end
end
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
tempData.a #=> 100
更新:在personal extensions library我添加了Hash#to_ostruct方法。这将递归地将哈希转换为包含所有嵌套哈希的OpenStruct
。
答案 1 :(得分:10)
还有另一种方法可以做到这一点。
JSON.parse(tempData.to_json, object_class: OpenStruct)
将给出对象
#<OpenStruct a=100, here=200, c="hello">
通过这种方式,嵌套的hash
也将转换为OpenStruct Object
tempData = {a: { b: { c: 3}}, foo: 200, msg: 'test msg'}
obj = JSON.parse(tempData.to_json, object_class: OpenStruct)
现在我们可以打电话了
obj.a.b.c # 3
obj.foo # 200
obj.msg # 'test msg'
希望这会对某人有所帮助。
答案 2 :(得分:5)
或者,如果它只是一个小脚本,那么扩展Hash
本身可能会更方便
class Hash
def method_missing sym,*
fetch(sym){fetch(sym.to_s){super}}
end
end
method_missing
是一种神奇的方法,只要您的代码尝试调用不存在的方法,就会调用该方法。 Ruby将在运行时拦截失败的调用,让你处理它,这样你的程序就可以优雅地恢复。上面的实现尝试使用方法名称作为符号访问哈希,使用方法名称作为字符串,并最终失败,Ruby的内置方法丢失错误。
NB 对于更复杂的脚本,添加此行为可能会破坏其他第三方gem,您可以使用模块 并扩展每个实例
module H def method_missing sym,* fetch(sym){fetch(sym.to_s){super}} end end the = { answer: 42 } the.extend(H) the.answer # => 42
为了更方便,您甚至可以将模块传播到 嵌套的哈希
module H def method_missing sym,* r = fetch(sym){fetch(sym.to_s){super}} Hash === r ? r.extend(H) : r end end the = { answer: { is: 42 } } the.extend(H) the.answer.is # => 42
答案 3 :(得分:2)
如果散列位于模块内,则可以使用define_method
动态定义该模块(或类)上的方法。例如:
module Version
module_function
HASH = {
major: 1,
minor: 2,
patch: 3,
}
HASH.each do |name, value|
define_method(name) do
return value
end
end
end
这将定义一个Version
模块,其major
,minor
和patch
方法分别返回1,2和3。
答案 4 :(得分:1)
您可以通过以下方式扩展Hash类。
class Hash
# return nil whenever the key doesn't exist
def method_missing(m, *opts)
if self.has_key?(m.to_s)
return self[m.to_s]
elsif self.has_key?(m.to_sym)
return self[m.to_sym]
end
return nil
# comment out above line and replace with line below if you want to return an error
# super
end
end