ruby-如何将哈希键转换为方法名称?

这是我的哈希:

tempData = {"a" => 100, "here" => 200, "c" => "hello"}

我需要像这样访问散列键:

tempData.a #100
tempData.here # 200
Sreeraj asked 2020-02-21T22:55:29Z
5个解决方案
89 votes

您可以将哈希值包装在OpenStruct中:

require 'ostruct'
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
os = OpenStruct.new tempData
os.a #=> 100
os.here #=> 200

如果您真的想要,也可以对OpenStruct类进行猴子修补,但我建议您不要这样做:

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

更新:在我的个人扩展库中,我添加了一个Hash#to_ostruct方法。 这将递归地将散列转换为包含所有嵌套散列的OpenStruct

Michael Kohl answered 2020-02-21T22:55:51Z
11 votes

还有另一种方法可以做到这一点。

hash

那会给对象hash

这样,嵌套的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'

希望这会帮助某人。

Engr. Hasanuzzaman Sumon answered 2020-02-21T22:56:33Z
6 votes

另外,如果只是一个小脚本,则扩展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 本身可能会更方便

class Hash
  def method_missing sym,*
    fetch(sym){fetch(sym.to_s){super}}
  end
end

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 是一种魔术方法,只要您的代码尝试调用不存在的方法,就会调用该方法。 Ruby将在运行时拦截失败的调用,并让您处理它,以便程序可以正常恢复。 上面的实现尝试使用方法名称作为符号,使用方法名称作为字符串来访问哈希,并最终由于Ruby的内置方法丢失错误而失败。

注意:对于更复杂的脚本,添加此行为可能会破坏其他第三方gem,您也可以使用模块   并扩展每个实例

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

为了更大的方便,您甚至可以将模块传播到   嵌套的哈希

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
akuhn answered 2020-02-21T22:57:16Z
2 votes

如果哈希在模块内部,则可以使用Version在该模块(或类)上动态定义方法。例如:

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模块,该模块具有分别返回1、2和3的majorminorpatch方法。

sferik answered 2020-02-21T22:57:41Z
1 votes

您可以通过以下方式扩展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
lsu_guy answered 2020-02-21T22:58:01Z
translate from https://stackoverflow.com:/questions/6423484/how-do-i-convert-hash-keys-to-method-names