Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

255
Views
Sum array values to hash

I have an array like

[
    [358, 202102, 5],
    [358, 202112, 5],
    [358, 202102, 10],
    [311, 202103, 5],
    [311, 202101, 1],
    [311, 202101, 1],
    [311, 202115, 8],
    [311, 202101, 1],
    [311, 202101, 1]
]

I need a hash like this:

{
    358 => { 
        202102 => 15,
        202112 => 5
    },
    311 => {
        202103 => 5,
        202101 => 4,
        202115 => 8
    }
}

The order does not matter. Only the third values from each row of the array must be added up.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You can solve this using Enumberable#each_with_object as follows

a = [
    [358, 202102, 5],
    [358, 202112, 5],
    [358, 202102, 10],
    [311, 202103, 5],
    [311, 202101, 1],
    [311, 202101, 1],
    [311, 202115, 8],
    [311, 202101, 1],
    [311, 202101, 1]
]

a.each_with_object(Hash.new {|h,k| h[k] = Hash.new(0)}) do |(k1,k2,val), obj| 
  obj[k1][k2] += val 
end 
# => {358=>{202102=>15, 202112=>5}, 311=>{202103=>5, 202101=>4, 202115=>8}}

What this does is iterates over the Array (a) with an accumulator Object (obj).

This object is a Hash with a default proc where every time a new key is added its value is assigned as a new Hash with a default value of 0.

In the block arguments we deconstruct the Array into 3 arguments (k1,k2,val) so on first pass it would look something like this:

k1 = 358
k2 = 202102
val = 5 
obj[k1] 
#=> {358=> {}} 
obj[k1][k2] 
#=> {358 => {202102 => 0 }}
obj[k1][k2] += val
obj
#=> {358 => {202102 => 5 }}
over 4 years ago · Santiago Trujillo Report

0

Another way is to use the methods Hash#update (aka merge!) and Hash#merge that employ blocks to determine the values of keys that are present in both hashes being merged. See the docs for definitions of the three block variables. I've used an underscore for the first block variables (the common key of the hashes being merged) to signify that it is not used in the block calculation.

a = [
    [358, 202102, 5],
    [358, 202112, 5],
    [358, 202102, 10],
    [311, 202103, 5],
    [311, 202101, 1],
    [311, 202101, 1],
    [311, 202115, 8],
    [311, 202101, 1],
    [311, 202101, 1]
]
a.each_with_object({}) do |(x,y,n),h|
  h.update(x=>{y=>n}) do |_,old1,new1|
    old1.merge(new1) { |_,old2,new2| old2+new2 }
  end
end
  #=> {358=>{202102=>15, 202112=>5}, 311=>{202103=>5, 202101=>4, 202115=>8}}
over 4 years ago · Santiago Trujillo Report

0

At first I create a hash of hashes with the default value 0. After that I just add the values of the hash of hashes up based on the last value in the array.

aoa =
[
    [358, 202102, 5],
    [358, 202112, 5],
    [358, 202102, 10],
    [311, 202103, 5],
    [311, 202101, 1],
    [311, 202101, 1],
    [311, 202115, 8],
    [311, 202101, 1],
    [311, 202101, 1]
]


hash = Hash.new { |h,k| h[k] = Hash.new(0) }
aoa.each { |ary|  hash[ary[0]][ary[1]] += ary[2]}

pp hash

output:

{358=>{202102=>15, 202112=>5}, 311=>{202103=>5, 202101=>4, 202115=>8}}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!