Sorting/accessing 通过嵌套哈希数组

Sorting/accessing through an array of nested hashes

我有一个包含姓名和年龄的散列数组:

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

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

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

在不定义 class 的情况下,我想做的是:

array.first.name # => "bill"

我该怎么做?

正在做:

def name
  array[0].keys
end 

将定义一个私有方法,不能在接收者上调用。

由于您的数组 array 由散列组成,当您执行 array.first 时,将返回一个散列 {"bill" => 12}

您现在可以定义可应用于 array.first 的方法 Hash#name (一个哈希)

这里:

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

你有:

h = array.first #=> {"bill" => 12} 
h.class         #=> Hash

所以如果你想创建一个方法 first,这样:

h.name #=> "bill"

您必须在其接收者 (h) 的 class 上定义 name,即 Hash。 @shivam 已经向您展示了如何做到这一点,但是(正如@AndrewMarshall 在评论中指出的那样)它污染了 class Hash。更好的方法是使用 Refinements.

Refinements 是对 v2.0 的实验性添加,然后在 v2.1 中进行了修改并永久保留。它提供了一种通过提供 "a way to extend a class locally".

来避免 "monkey-patching" 的方法

我们可以这样做。首先,模块 M:

中的 refine Hash
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)

激活优化后,我们可以在 h 上调用 name:

using M
h.name
  #-> bill

改进适用于文件的其余部分,但不适用于其他文件中的代码。假设我们要将以下内容添加到当前文件中:

class A
  def greeting(h)
    puts "Hello, #{h.name}"
  end
end

然后:

A.new.greeting({"bill" => 12})
  #-> Hello, bill