必须有一个更清洁的方法来做到这一点

时间:2010-10-09 03:40:37

标签: ruby-on-rails ruby arrays hash multidimensional-array

我有这段代码here并且它有效,但必须有更好的方法.....我需要两个看起来像这样的数组

[ 
{
  "Vector Arena - Auckland Central, New Zealand" => { 
    "2010-10-10" => [
       "Enter Sandman", 
       "Unforgiven", 
       "And justice for all"
    ]
  }
},  
{
  "Brisbane Entertainment Centre - Brisbane Qld, Austr..." => { 
    "2010-10-11" => [
      "Enter Sandman"
    ]
  }
}
]

一个过去和一个即将到来...我遇到的问题是我重复自己,虽然它有效但我想要清理它...这是我的data ..

1 个答案:

答案 0 :(得分:1)

试试这个:

h = Hash.new {|h1, k1| h1[k1] = Hash.new{|h2, k2| h2[k2] = []}}
result, today = [ h, h.dup], Date.today

Request.find_all_by_artist("Metallica", 
 :select => "DISTINCT venue, showdate, LOWER(song) AS song"
).each do |req|
  idx = req.showdate < today ? 0 : 1
  result[idx][req.venue][req.showdate] << req.song.titlecase
end

注1

在第一行中,我正在初始化散列哈希值。当访问不存在的密钥时,外部哈希创建内部哈希。摘自Ruby Hash documentation

If this hash is subsequently accessed by a key that doesn‘t correspond to a hash 
entry, the block will be called with the hash object and the key, and should 
return the default value. It is the block‘s responsibility to store the value in 
the hash if required. 

当访问不存在的日期时,内部哈希创建并清空数组。

例如:构造一个包含内容作为值和日期作为键的哈希:

没有默认阻止:

h = {}
list.each do |data|
  h[data.date] = [] unless h[data.date]
  h[data.date] << data.content
end

使用默认块

h = Hash.new{|h, k| h[k] = []}
list.each do |data|
  h[data.date] << data.content
end

第二行只是创建一个包含两个项目的数组来保存过去和未来的数据。由于过去和现在都将数据存储为Hash of Hash of Array,我只需复制该值。

第二行也可以写成

result = [ h, h.dup]
today = Date.today