свертывание рубиновых объектов в хэше - PullRequest
0 голосов
/ 04 марта 2012

У меня есть объект, который выглядит так:

[{"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"}]

Я бы хотел вернуть его как

 [{"amount":"1000.0","when":"2012-03"},
 {"amount":"200.0","when":"2012-04"}]

Есть ли элегантный способ сделать это? У меня есть версия, которая работает, но на самом деле она выглядит глупо

@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

1 Ответ

6 голосов
/ 04 марта 2012

Предполагая, что вы распаковали свой JSON в Ruby Array of Hashes:

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"}
]

Тогда вы можете сделать это:

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

Это оставит вас с этим в compressed:

[
    {:when => "2012-03", :amount => 1000},
    {:when => "2012-04", :amount => 200}
]

И вы можете преобразовать это в JSON обычным способом.

group_by разделяет исходный массив, используя только компоненты года и месяца.Тогда вам просто нужно переставить вещи и суммировать часть сгруппированных хэшей, используя map и inject.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...