如何在ruby中制作动态多维数组?

我有一个关于多维数组的初学ruby问题。

我想按年份和月份对条目进行排序。 所以我想创建一个包含年 – >月 – >月份条目的多维数组

所以数组就像:

2009 -> 08 -> Entry 1 -> Entry 2 09 -> Entry 3 2007 -> 10 -> Entry 5 

我现在有:

 @years = [] @entries.each do |entry| timeobj = Time.parse(entry.created_at.to_s) year = timeobj.strftime("%Y").to_i month = timeobj.strftime("%m").to_i tmparr = [] tmparr <entry} @years.push(year) @years << tmparr end 

但是当我尝试遍历岁月数组时,我得到:“未定义的方法`每个’为2009:Fixnum”

也试过:

 @years = [] @entries.each do |entry| timeobj = Time.parse(entry.created_at.to_s) year = timeobj.strftime("%Y").to_i month = timeobj.strftime("%m").to_i @years[year][month] << entry end 

您收到错误是因为FixNum (即数字)被推送到数组上,在读取@years.push(year)

你使用Arrays开始的方法有点缺陷; 数组非常适合保存有序的项目列表。 在您的情况下,您有从键到值的映射,这对于哈希来说是完美的。

在第一级,键是年,值是哈希值。 第二级的哈希包含月份的键和条目数组的值。

在这种情况下,代码的典型输出看起来像(基于您的示例):

 { 2009 => { 8 => [Entry1, Entry2], 9 => [Entry3] }, 2007 => { 10 => [Entry5] }} 

但请注意,年和月的顺序不保证按任何特定顺序排列。 解决方案通常是在您想要访问它们时订购密钥。 现在,一个代码将生成这样的输出(基于您的代码布局,虽然可以做得更多):

 @years = {} @entries.each do |entry| timeobj = Time.parse(entry.created_at.to_s) year = timeobj.strftime("%Y").to_i month = timeobj.strftime("%m").to_i @years[year] ||= {} # Create a sub-hash unless it already exists @years[year][month] ||= [] @years[year][month] << entry end 

您可以使用group_bymap的组合将嵌套数组结构放在一行中:

 @entries.group_by {|entry| entry.created_at.year }.map { |year, entries| [year, entries.group_by {|entry| entry.created_at.month }] } 

我正在使用哈希表而不是数组,因为我认为这可能更有意义。 但是,如果这是您喜欢的,那么改回使用数组是相当简单的。

 entries = [ [2009, 8, 1], [2009, 8, 2], [2009, 9, 3], [2007, 10, 5] ] years = Hash.new entries.each { |e| year = e[0] month = e[1] entry = e[2] # Add to years array years[year] ||= Hash.new years[year][month] ||= Array.new years[year][month] << entry } puts years.inspect 

输出为: {2007=>{10=>[5]}, 2009=>{8=>[1, 2], 9=>[3]}}

 # create a hash of hashes of array @years = Hash.new do |h,k| h[k] = Hash.new do |sh, sk| sh[sk] = [] end end @entries.each do |entry| timeobj = Time.parse(entry.created_at.to_s) year = timeobj.year month = timeobj.month @years[year][month] << entry end