通过嵌套哈希数组进行排序/访问

时间:2015-03-28 13:51:31

标签: ruby hash

我有一系列名称和年龄的哈希:

array = [ {"bill" => 12}, {"tom" => 13}, {"pat" => 14} ]

我意识到,通过调用first方法,会发生这种情况:

array.first # => {"bill" => 12}

如果没有定义课程,我想做:

array.first.name # => "bill"

我该怎么做?

这样做的:

def name
  array[0].keys
end 

将定义一个私有方法,该方法无法在接收方上调用。

2 个答案:

答案 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"]