Reputation: 13
I have an array
[
{
"week_year": "49-2021",
"total": 6.5
},
{
"week_year": "45-2021",
"total": 28.5
},
{
"week_year": "45-2021",
"total": 6.5
},
{
"week_year": "44-2021",
"total": 6.5
},
{
"week_year": "46-2021",
"total": 14.5
}
]
I want to group it by the same week_year and sum its total per week. Any other way to do that?
Upvotes: 0
Views: 334
Reputation: 110685
If arr
is the array given in the question one could write
arr.each_with_object(Hash.new(0)) { |g,h| h[g[:week_year]] += g[:total] }
#=> {"49-2021"=>6.5, "45-2021"=>35.0, "44-2021"=>6.5, "46-2021"=>14.5}
This makes a single pass through the array and requires less memory than does the use of Enumerable#group_by
. Arguably, it also reads better. Whether it's faster is an open question.
This employs the form of Hash::new that takes an argument--called the default value--and no block. If a hash h
is so-defined, then, possibly after keys have been added, if h
does not have a key k
, h[k]
returns the default value. The default value is commonly chosen to be zero, as it is here.
The expression
h[g[:week_year]] += g[:total]
expands to
h[g[:week_year]] = h[g[:week_year]] + g[:total]
so if h
does not have a key g[:week_year]
this becomes
h[g[:week_year]] = 0 + g[:total]
Upvotes: 1
Reputation: 33420
If the output needed is like { week_year => total }
then you can use a combination of group_by
, transform_values
and sum
:
arr
.group_by { |hash| hash[:week_year] }
.transform_values { |arr| arr.sum { |hash| hash[:total] } }
# {"49-2021"=>6.5, "45-2021"=>35.0, "44-2021"=>6.5, "46-2021"=>14.5}
Upvotes: 1
Reputation: 3251
You can use group_by in combination with transform_values:
array.group_by { |a| a[:week_year] }
.transform_values { |values| values.sum { |value| value[:total] } }
Which will return:
{
"49-2021" => 6.5,
"45-2021" => 35.0,
"44-2021" => 6.5,
"46-2021" => 14.5
}
Upvotes: 0