在哈希中折叠ruby对象

ed1*_*d1t 0 ruby hash

我有一个看起来像这样的对象:

[{"amount":"500.0","when":"2012-03-13"},
 {"amount":"500.0","when":"2012-03-24"},
 {"amount":"100.0","when":"2012-04-14"},
 {"amount":"100.0","when":"2012-04-16"}]
Run Code Online (Sandbox Code Playgroud)

我想把它拿回来

 [{"amount":"1000.0","when":"2012-03"},
 {"amount":"200.0","when":"2012-04"}]
Run Code Online (Sandbox Code Playgroud)

有一种优雅的方式吗?我有一个可行的版本,但看起来真的很糟糕

@exps = Expense.find(:all, :select => ["`when`", "amount"])  
@exp_month = {}
@result = []

@exps.each do |e|
  month = "#{e.when.year}-#{e.when.month}"
  @exp_month[month] = @exp_month.has_key?(month) ? @exp_month[month] + e.amount : e.amount     
end

@exp_month.keys.each do |m|    
  @result << {"when" => m, "amount" => @exp_month[m]}
end
Run Code Online (Sandbox Code Playgroud)

mu *_*ort 6

假设您已将JSON解压缩为Ruby哈希数组:

a = [
    {:amount => "500.0", :when => "2012-03-13"},
    {:amount => "500.0", :when => "2012-03-24"},
    {:amount => "100.0", :when => "2012-04-14"},
    {:amount => "100.0", :when => "2012-04-16"}
]
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

compressed = a.group_by { |h| h[:when][0,7] }.map do |k, v|
    {
        :when   => k,
        :amount => v.inject(0) { |i, h| i + h[:amount].to_i }
    }
end
Run Code Online (Sandbox Code Playgroud)

这会让你知道compressed:

[
    {:when => "2012-03", :amount => 1000},
    {:when => "2012-04", :amount => 200}
]
Run Code Online (Sandbox Code Playgroud)

并且您可以通常的方式将其转换为JSON.

group_by块只使用年份和月份组成部分原始数组.然后,你就必须重新安排事物,总结利用分组散列的切片mapinject.

  • 我是为了同样的事情,你打败了我!我建议一个更健壮的月份分组:`group_by {| h | Date.strptime(H [:当]).的strftime( "%Y-%米")` (2认同)