I have an Ruby array that looks like this:
[{ :date => '2018-02-01', :capacity => 5, :used_capacity => 3 },
{ :date => '2018-02-01', :capacity => 10, :used_capacity => 3 },
{ :date => '2018-02-02', :capacity => 5, :used_capacity => 3 }]
And I need to the hashes if they have the same date and sum the capacity and used_capacity fields.
So it needs to become:
[{ :date => '2018-02-01', :capacity => 15, :used_capacity => 6 },
{ :date => '2018-02-02', :capacity => 5, :used_capacity => 3 }]
Can anyone push me in the right direction?
Thnx!
input = [{ :date => '2018-02-01', :capacity => 5, :used_capacity => 3 },
{ :date => '2018-02-01', :capacity => 10, :used_capacity => 3 },
{ :date => '2018-02-02', :capacity => 5, :used_capacity => 3 }]
input.group_by { |h| h[:date] }.
values.
map do |a|
a.reduce do |acc, h|
acc.merge(h) { |k, v1, v2| k == :date ? v1 : v1 + v2 }
end
end
arr = [{ :date => '2018-02-01', :capacity => 5, :used_capacity => 3 },
{ :date => '2018-02-01', :capacity => 10, :used_capacity => 3 },
{ :date => '2018-02-02', :capacity => 5, :used_capacity => 3 }]
arr.each_with_object({}) do |g,h|
h.update(g[:date]=>g) do |_,oh,nh|
oh.merge(nh) { |k,ov,nv| k==:date ? ov : ov+nv }
end
end.values
#=> [{:date=>"2018-02-01", :capacity=>15, :used_capacity=>6},
# {:date=>"2018-02-02", :capacity=>5, :used_capacity=>3}]
This uses the forms of Hash#update (aka merge!
) and Hash#merge that employ a block to determine the values of keys that are present in both hashes being merged. update
.