当前位置:  开发笔记 > 编程语言 > 正文

hash ['key']到Ruby中的hash.key

如何解决《hash['key']到Ruby中的hash.key》经验,为你挑选了5个好方法。

我有一个哈希

foo = {'bar'=>'baz'}

我想打个电话 foo.bar #=> 'baz'

我的动机是将activerecord查询重写为原始sql查询(使用Model#find_by_sql).这将返回一个带有SELECT子句值作为键的哈希.但是,我现有的代码依赖于object.method点表示法.我想做最小的代码重写.谢谢.

编辑:看来Lua有这个功能:

point = { x = 10, y = 20 }   -- Create new table
print(point["x"])            -- Prints 10
print(point.x)               -- Has exactly the same meaning as line above

Hooopo.. 81

>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #
>> foo_obj.bar
=> "baz"
>>

@Steen如果你谷歌"红宝石方法缓存",前几个点击将由查理萨默维尔和已故的詹姆斯戈利克解释它.在Ruby 2.1之前,实例化一个ostruct方法转储了*whole*方法缓存.在2.1+中,它为所有ostruct实例及其子类的实例转储方法高速缓存. (4认同)

不鼓励使用OpenStruct,因为每个实例化都会使Ruby方法缓存失效,从而减慢整个应用程序的速度. (3认同)


Avdi.. 35

您正在寻找的是OpenStruct.它是标准库的一部分.



1> Hooopo..:
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #
>> foo_obj.bar
=> "baz"
>>


@Steen如果你谷歌"红宝石方法缓存",前几个点击将由查理萨默维尔和已故的詹姆斯戈利克解释它.在Ruby 2.1之前,实例化一个ostruct方法转储了*whole*方法缓存.在2.1+中,它为所有ostruct实例及其子类的实例转储方法高速缓存.
不鼓励使用OpenStruct,因为每个实例化都会使Ruby方法缓存失效,从而减慢整个应用程序的速度.

2> Avdi..:

您正在寻找的是OpenStruct.它是标准库的一部分.



3> Gabor Garami..:

一个好的解决方案

class Hash
  def method_missing(method, *opts)
    m = method.to_s
    if self.has_key?(m)
      return self[m]
    elsif self.has_key?(m.to_sym)
      return self[m.to_sym]
    end
    super
  end
end

注意:此实现只有一个已知错误:

x = { 'test' => 'aValue', :test => 'bar'}
x.test # => 'aValue'

如果您更喜欢符号查找而不是字符串查找,那么交换两个"if"条件


我一直在做这个`self [m] || 自[m.to_s] || super`而不是`if/else`块

4> Dafydd Rees..:

而不是将所有内容复制到散列中,您只需向Hash添加一些行为即可进行查找.

如果添加此定义,则扩展Hash以将所有未知方法作为哈希查找处理:

class Hash
  def method_missing(n)
    self[n.to_s]
  end
end

请记住,这意味着如果在哈希上调用错误的方法,您将永远不会看到错误 - 您将获得相应的哈希查找将返回的任何内容.

只需将方法放在特定的哈希值上,或者根据需要添加多个哈希值,就可以大大减少调试问题:

a={'foo'=>5, 'goo'=>6}
def a.method_missing(n)
   self[n.to_s]
end

另一个观察是,当method_missing系统调用它时,它会给你一个Symbol参数.我的代码将其转换为String.如果你的散列键不是字符串此代码永远不会返回的价值观-如果你通过按键符号而不是字符串,可以替换nn.to_s以上.


有人在我参与的一个大项目中做到了这一点.它引起了各种微妙的错误,因为对系统中任何哈希的错误方法调用只返回nil,而不是用NoMethodError警告我们.从系统中删除它需要花费很长时间,因为整个系统的代码都依赖于它.这是我见过的最灾难性的代码类扩展之一.
为了(大部分)解决这个问题,你可以做`if has_key?n.to_s然后self [n.to_s] else引发NoMethodError`

5> steel..:

有一些宝石。我最近在RubyGems上发布我的宝石时,发现了我的宝石hash_dot和其他名称相似的宝石,包括dot_hash。

HashDot允许使用点表示法语法,同时仍可解决@avdi解决的NoMethodErrors问题。它比使用OpenStruct创建的对象更快,更可遍历。

require 'hash_dot'
a = {b: {c: {d: 1}}}.to_dot
a.b.c.d => 1

require 'open_struct'
os = OpenStruct.new(a)
os.b => {c: {d: 1}}
os.b.c.d => NoMethodError

当调用非方法时,它也保持预期的行为。

a.non_method => NoMethodError

请随时向HashDot提交改进或错误。

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有