执行以下数据结构转换的“Rubyist”方式是什么:
我有
incoming = [ {:date => 20090501, :width => 2}, {:date => 20090501, :height => 7}, {:date => 20090501, :depth => 3}, {:date => 20090502, :width => 4}, {:date => 20090502, :height => 6}, {:date => 20090502, :depth => 2}, ]
我希望通过以下方式折叠这些:日期,以
结束outgoing = [ {:date => 20090501, :width => 2, :height => 7, :depth => 3}, {:date => 20090502, :width => 4, :height => 6, :depth => 2}, ]
如果列的每一行中的列顺序相同,那么最后一步也可以使用数组数组。另外,重要的是,我事先并不知道所有的哈希键(也就是说,我不知道:宽度,高度,或:深度 - 它们可能是:猫,狗,和:仓鼠)。
答案 0 :(得分:8)
如果使用Ruby 1.8.7或Ruby 1.9+,以下代码可以很好地阅读:
incoming.group_by{|hash| hash[:date]}.map do |_, hashes|
hashes.reduce(:merge)
end
块属性(_,哈希)中的下划线表示我们不需要/关心该特定属性。
#reduce是#inject的别名,用于将集合缩减为单个项目。在新的Ruby版本中,它还接受一个符号,这是用于执行缩减的方法的名称。
首先调用集合中第一个项目的方法,然后将第二个项目作为参数。然后,它会在结果上再次调用该方法,并将第三个项目作为参数,依此类推,直到没有其他项目为止。
[1, 3, 2, 2].reduce(:+) => [4, 2, 2] => [6, 2] => 8
答案 1 :(得分:2)
这是一个班轮:)
incoming.inject({}){ |o,i| o[i[:date]]||=[];o[i[:date]]<<i;o}.map{|a| a[1].inject(){|o,i| o.merge(i)}}
但实际上前一篇文章更清晰,也可能更快。
编辑:进行一些优化:
p incoming.inject(Hash.new{|h,k| h[k]=[]}){ |o,i| o[i[:date]]<<i;o}.map{|a| a[1].inject(){|o,i| o.merge(i)}}
答案 2 :(得分:2)
简明的解决方案:
incoming = [ {:date => 20090501, :width => 2},
{:date => 20090501, :height => 7},
{:date => 20090501, :depth => 3},
{:date => 20090502, :width => 4},
{:date => 20090502, :height => 6},
{:date => 20090502, :depth => 2},
]
temp = Hash.new {|hash,key| hash[key] = {}}
incoming.each {|row| temp[row[:date]].update(row)}
outgoing = temp.values.sort {|*rows| rows[0][:date] <=> rows[1][:date]}
这里唯一棘手的是Hash构造函数,它允许您提供在访问不存在的键时调用的块。所以我让Hash创建一个空哈希,让我们用我们找到的值进行更新。然后我只使用日期作为哈希键,按日期对哈希值进行排序,然后我们进行了转换。
答案 3 :(得分:0)
试试这个:
incoming = [ {:date => 20090501, :width => 2},
{:date => 20090501, :height => 7},
{:date => 20090501, :depth => 3},
{:date => 20090502, :width => 4},
{:date => 20090502, :height => 6},
{:date => 20090502, :depth => 2},
]
# Grouping by `:date`
temp = {}
incoming.each do |row|
if temp[row[:date]].nil?
temp[row[:date]] = []
end
temp[row[:date]] << row
end
# Merging it together
outcoming = []
temp.each_pair do |date, hashlist|
res = {}
hashlist.each do |hash|
res.merge!(hash)
end
outcoming << res
end
有关hash
成员的信息,请参阅this page
订购很重要时,必须使用锯齿状数组:
incoming = [ {:date => 20090501, :width => 2},
{:date => 20090501, :height => 7},
{:date => 20090501, :depth => 3},
{:date => 20090502, :width => 4},
{:date => 20090502, :height => 6},
{:date => 20090502, :depth => 2},
]
# Grouping by `:date`
temp = {}
incoming.each do |row|
if temp[row[:date]].nil?
temp[row[:date]] = []
end
key = row[:date]
row.delete :date
temp[key] << row
end
# Merging it together
outcoming = []
temp.each_pair do |date, hashlist|
res = [:date, date]
hashlist.each do |hash|
hash.each_pair {|key, value| res << [key, value] }
end
outcoming << res
end