There are many ways to do this. (You may have noticed that I've done a lot of editing of my answer, explaining in some detail how a method works, only to realize there's a better way to do it, so out comes the machete.) Here are two solutions. The first was inspired by the approach you took, but I've tried to package it to be more Ruby-like. I'm not sure what constitutes a valid "name", so I've put that determination in a separate method that can be easily changed.
Code
def name_valid?(name)
name[0..3] == "name"
end
data.each_with_object(Hash.new(0)) {|h,g|
(g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1) if name_valid?(h["name"])}
#=> {{"id"=>"name1", "priority"=>"1"}=>2,
# {"id"=>"name2", "priority"=>"1"}=>1,
# {"id"=>"name2", "priority"=>"2"}=>1}
Explanation
Enumerable#each_with_object creates an initially-empty hash with default value zero that is represented by the block variable g
. g
is built by adding hash elements created from the the elements of data
:
g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1
If the hash g
has the key
{"id"=>h["name"],"priority"=>h["priority"]}
the value associated with the key is incremented by one. If h
does not have this key,
g[{"id"=>h["name"],"priority"=>h["priority"]}]
is set equal to zero before
g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1
is invoked, so the value becomes 1
.
Alternative Method
Code
data.each_with_object({}) do |h,g|
hash = { { "id"=>h["name"], "priority"=>h["priority"] } => 1 }
g.update(hash) { |k, vg, _| vg + 1 } if name_valid?(h["name"])
end
#=> {{"id"=>"name1", "priority"=>"1"}=>2,
# {"id"=>"name2", "priority"=>"1"}=>1,
# {"id"=>"name2", "priority"=>"2"}=>1}
Explanation
Here, I've used Hash#update (aka Hash#merge!
) to merge each element of data
(a hash) into the initially-empty hash h
(provided the value of "name"
is valid). update
's block
{ |k, vg, _| vg + 1 }
is invoked if and only if the merged hash (g
) and the merging hash (hash
) have the same key, k
, in which case the block returns the value of the key. Note the third block variable is the value for the key k
for the hash hash
. As we do not use that value, I've replaced it with the placeholder _
.