我有一系列名称和年龄的哈希:
array = [ {"bill" => 12}, {"tom" => 13}, {"pat" => 14} ]
我意识到,通过调用first
方法,会发生这种情况:
array.first # => {"bill" => 12}
如果没有定义课程,我想做:
array.first.name # => "bill"
我该怎么做?
这样做的:
def name
array[0].keys
end
将定义一个私有方法,该方法无法在接收方上调用。
答案 0 :(得分:1)
你有:
h = array.first #=> {"bill" => 12}
h.class #=> Hash
所以如果你想创建一个方法first
,那么:
h.name #=> "bill"
您必须在其接收者(name
)的类上定义h
,即Hash
。 @shivam向您展示了如何做到这一点,但(正如@AndrewMarshall在评论中指出的那样)它污染了类Hash
。更好的方法是使用Refinements
。
Refinements是对v2.0的实验性补充,然后在v2.1中进行了修改并永久化。它提供了一种通过提供“一种在本地扩展类的方法”来避免“猴子修补”的方法。
我们可以这样做。首先,模块refine
中的Hash
M
:
module M
refine Hash do
def name
keys.first
end
end
end
在模块上调用关键字using
之前,细化无效:
h = {"bill" => 12}
puts h.name
#-> undefined method `name' for {"bill"=>12}:Hash (NoMethodError)
激活优化后,我们可以在name
上调用h
:
using M
h.name
#-> bill
细化适用于文件的其余部分,但不适用于其他文件中的代码。假设我们要将以下内容添加到当前文件中:
class A
def greeting(h)
puts "Hello, #{h.name}"
end
end
然后:
A.new.greeting({"bill" => 12})
#-> Hello, bill
答案 1 :(得分:0)
由于您的数组array
包含哈希值,因此当您array.first
时,会返回一个哈希值{"bill" => 12}
。
您现在可以定义可应用于Hash#name
的方法array.first
(哈希)
下面:
class Hash
def name
self.keys.first
end
end
array.first.name
# => "bill"
#to print all names
array.each{|a| puts a.name}
# bill
# tom
# pat
# or collect them in an Array
array.map(&:name)
# => ["bill", "tom", "pat"]