Syildiz
Syildiz

Reputation: 79

To sum up same keys values in Ruby

I have below array which has to sum up same keys values as {'dogs' => 11, 'cats' => 3}.

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

I have found the below answer while I was searching on stackoverflow (I lost the link:( )

print animals.each_with_object(Hash.new(0)) { |(k, v), h| h[k] += v }

However I can't make it clear in my mind that what do k,v and h represents exactly. Because "h" is staying second argument of the block code but it continious with h[k] . Could anyone explain the code clearly?

Thank you too much.

Upvotes: 0

Views: 835

Answers (3)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

animals.map(&:dup).
        group_by(&:shift).
        map { |k, v| [k, v.flatten.inject(:+)] }.
        to_h
#⇒ {"dogs"=>11, "cats"=>3} 

Upvotes: 2

Santhosh
Santhosh

Reputation: 29144

Playing around with the Array to understand it better

animals.each {|arr| puts arr.inspect }
# ["dogs", 4]
# ["cats", 3]
# ["dogs", 7]

animals.each {|k, v| puts "k -> #{k}, v -> #{v}" }
# k -> dogs, v -> 4
# k -> cats, v -> 3
# k -> dogs, v -> 7

animals.each_with_object({}) do |(k, v), h| 
  puts "k -> #{k}, v -> #{v}, h -> #{ h.inspect }"
end
# k -> dogs, v -> 4, h -> {}
# k -> cats, v -> 3, h -> {}
# k -> dogs, v -> 7, h -> {}

animals.each_with_object({}) do |(k, v), h|
  h[v] = k
  puts "k -> #{k}, v -> #{v}, h -> #{ h.inspect }"
end
# k -> dogs, v -> 4, h -> {4=>"dogs"}
# k -> cats, v -> 3, h -> {4=>"dogs", 3=>"cats"}
# k -> dogs, v -> 7, h -> {4=>"dogs", 3=>"cats", 7=>"dogs"}

Upvotes: 1

tadman
tadman

Reputation: 211670

In simple terms:

animals.each_with_object(Hash.new(0)) do |(key, value), hash|
  hash[key] += value
end

Here (k,v) is an expansion of each pair in the animals hash, which is key-value. h represents the "object" that's passed along with this iteration.

That's a fairly standard pattern in terms of Ruby code.

Upvotes: 3

Related Questions