Search code examples
rubysumruby-hash

Sum of particular values in a Ruby hash


I have two hashes:

first = { 1 => [15, 15, 15, 8], 4 => [11, 12, 7, 7], 5 => [14, 17, 13, 13],
          6 => [19, 19, 15, 15], 7 => [5, 12, 12, 12], 8 => [10, 14, 14, 14], 
          9 => [8, 7, 8, 8] } 

second = { 1 => [0, 1, 2], 4 => [2, 3], 5 => [2, 3], 6 => [0, 1, 2, 3], 
           7 => [1, 2, 3], 8 => [1, 2, 3], 9 => [2, 3] }

As you see they both use same keys, but values are different. second's values contains ranges of indexes of the first's values and I need to sum only those first's values that are in those ranges.

The expected output:

result = { 1 => [45], 4 => [14], 5 => [26], etc }

Solution

  • A straightforward way is to say exactly what you mean:

    first.map { |k, v| [ k, [ v.values_at(*second[k]).sum ] ] }.to_h
    

    If your version of Ruby doesn't have Array#sum then use inject(:+):

    first.map { |k, v| [ k, [ v.values_at(*second[k]).inject(:+) ] ] }.to_h
    

    You could also skip the map/to_h business by using each_with_object instead:

    first.each_with_object({}) { |(k, v), h| h[k] = [ v.values_at(*second[k]).inject(:+) ] }
    

    A little time with the Array#values_at documentation might be fruitful as would the Enumerable documentation.