Sum of hash value inside the array In ruby

data.each_with_object({}) do |g,h|
  h.update(g[:lineItemKey]=>g) do |_k, old_hash, new_hash|
    old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
  end
end.values
  #=> [
  # {:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
  #  :quantity=>5, :unitPrice=>5.76},
  # {:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50", :name=>"22 Long",
  #  :quantity=>2, :unitPrice=>7.6},
  # {:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
  #  :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
  # ]

Note that the receiver of values is

{
   57=>{:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
        :quantity=>5, :unitPrice=>5.76},
  168=>{:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
        :name=>"22 Long", :quantity=>2, :unitPrice=>7.6},
  236=>{:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
        :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
}

This uses the form of Hash#update (a.k.a merge!) that employs a block to compute the values of keys that are present in both hashes being merged. Here that block is

do |_k, old_hash, new_hash|
  old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
end

See the doc for definitions of the three block variables. The underscore preceding k (the common key) is intended tro signal to the reader that it is not used in the block calculation (a common convention which is often just the underscore alone).


Input

data = 
  [
    { :lineItemKey=>57, :sku=>"12GA-RIO", 
      :name=>"12 Gauge", :quantity=>4, :unitPrice=>5.76 },
    { :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50", 
      :name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
    { :lineItemKey=>57, :sku=>"12GA-RIO", 
      :name=>"12 Gauge", :quantity=>1, :unitPrice=>5.76 }, 
    { :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
      :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
  ]

Code

p data.group_by { |x| x[:lineItemKey] }
      .values
      .map { |arr| arr.reduce { |h1, h2| h1.merge(h2) { |k, oldv, newv| k.eql?(:quantity) ? oldv += newv : oldv } } }

Output

[
  { :lineItemKey=>57, :sku=>"12GA-RIO", 
    :name=>"12 Gauge", :quantity=>5, :unitPrice=>5.76 }, 
  { :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",  
    :name=>"22 Long", :quantity=>2, :unitPrice=>7.6 }, 
  { :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20", 
    :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]