-7
animals = [['dogs', 4], ['cats', 3], ['dogs', 7]]

Convert animals to:

{'dogs' => 11, 'cats' => 3}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
CJ Jean
  • 971
  • 1
  • 8
  • 10

5 Answers5

4

You can use each_with_object:

=> array =  [['dogs', 4], ['cats', 3], ['dogs', 7]]
=> array.each_with_object(Hash.new(0)) do |(pet, n), accum| 
=>   accum[pet] += n
=> end
#> {'dogs' => 11, 'cats' => 3}
Roman Kiselenko
  • 43,210
  • 9
  • 91
  • 103
3

I used Enumerable#group_by. A better way is to use a counting hash, which @Зелёный has done.

animals = [['dogs', 4], ['cats', 3], ['dogs', 7]]

animals.group_by(&:first).tap { |h| h.keys.each { |k| h[k] = h[k].transpose[1].sum } }
  #=> {"dogs"=>11, "cats"=>3}
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
2
data = [['dogs', 4], ['cats', 3], ['dogs', 7]]
data.dup
    .group_by(&:shift)
    .map { |k, v| [k, v.flatten.reduce(:+)] }
    .to_h

With Hash#merge:

data.reduce({}) do |acc, e|
  acc.merge([e].to_h) { |_, v1, v2| v1 + v2 }
end

data.each_with_object({}) do |e, acc|
  acc.merge!([e].to_h) { |_, v1, v2| v1 + v2 }
end
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
1

This is another method that is done by iterating through each array element:

animals = [['dogs', 4], ['cats', 3], ['dogs', 7]]

result = Hash.new(0)

animals.each do |animal|
    result[animal[0]] += animal[1].to_i
end

p result
Fatos Morina
  • 456
  • 1
  • 7
  • 14
-1

You can use the to_h method if you are using ruby <= 2.1.

For example:

animals = [['dogs', 4], ['cats', 3], ['dogs', 7]]
animals.group_by(&:first).map { |k,v| [k,v.transpose.last.reduce(:+)]}.to_h # return {"dogs"=>11, "cats"=>3}
mijailr
  • 71
  • 1
  • 12