arr = [
{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}
]
arr.each_with_object({}) do |g,h|
h.update(g[:id]=>g) { |_,o,n| o.merge(pages: o[:pages] + n[:pages]) }
end.values
#=> [{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>30},
# {:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}]
Обратите внимание, что получатель values
равен
{1=>{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>30},
2=>{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}}
Используется форма Hash # update (он же merge!
), который использует блок
{ |_,o,n| o.merge(pages: o[:pages] + n[:pages]) }
для определения значений ключей (переменная блока _
), которые присутствуют в обоих объединяемых хэшах.См. Документ для объяснения переменных блока o
и n
.
Hash#update
и Enumerable # group_by - это два метода, к которым обычно обращаются при решении проблемэтот вид.Любой может быть использован.Они примерно одинаковы по эффективности, поэтому выбор во многом зависит от личных предпочтений.