我有一个关于多维数组的初学红宝石问题。
我想按年份和月份对条目进行排序。所以我想创建一个包含年份的多维数组 - >月 - >月份条目
所以数组就像:
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 << {month=>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
答案 0 :(得分:11)
您收到错误是因为FixNum
(即数字)被推送到数组上的@years.push(year)
行。
使用Arrays开始的方法有点缺陷;数组非常适合保存有序的项目列表。在你的情况下,你有一个从键到值的映射,这对哈希来说是完美的。
在第一级,键是年,值是哈希值。第二级的哈希包含几个月的键和条目数组的值。
在这种情况下,代码的典型输出看起来像(基于您的示例):
{ 2009 => { 8 => [Entry1, Entry2], 9 => [Entry3] }, 2007 => { 10 => [Entry5] }}
但请注意,年和月的顺序不保证按任何特定顺序排列。解决方案通常是在您想要访问它们时订购密钥。现在,一个代码可以生成这样的输出(基于你的代码布局,虽然可以做很多 rubier ):
@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
答案 1 :(得分:8)
您可以使用group_by
和map
的组合在一行中获取嵌套数组结构:
@entries.group_by {|entry| entry.created_at.year }.map { |year, entries| [year, entries.group_by {|entry| entry.created_at.month }] }
答案 2 :(得分:4)
我正在使用哈希表而不是数组,因为我认为这可能更有意义。但是,如果这是你喜欢的,那么改回使用数组是相当简单的。
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]}}
答案 3 :(得分:4)
# 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