From: Trans Date: 2007-03-13T21:03:24+09:00 Subject: Re: non-destructive merging of hashes in array On Mar 12, 10:01 pm, "Giles Bowkett" wrote: > Hi, I have an array of hashes. The keys in the hashes represent the same things. > > eg: > > h1 = {:rabbits => 5} > h2 = {:rabbits => 10} > > bunnies = [h1, h2] > > I want to end up with this: > > {:rabbits => 15} > > It's a trivial task, but what's the quickest way to get there? I'm > certain it can be done on one line. > > I know there's a Hash#update, but it appears that it would just > replace the 10 with 5, or vice versa, rather than adding them up. > > This works, but it seems clunky: > > hashes.each do |h| > h.each do |k, v| > if new_hash[k] > new_hash[k] += v > else > new_hash[k] = v > end > end > end > > It can be crammed all onto one line, too, but there must be a nicer way. (SORRY IF THIS GETS POSTED TWICE) The inject/merge solutions are good, but they are one trick ponies. How about something like: OpenCollection[h1, h2].rabbits.sum It shouldn't be too hard to write: require 'ostruct' class OpenCollection class << self ; alias :[] :new ; end def initialize(*hashes) @opens = hashes.collect { |h| OpenStruct.new(h) } end def method_missing(sym, *args) @opens.collect{ |o| o.send(sym) } end end Actually, I'd use Facets OpenObject instead OpenStruct myself, but that's just me. You'll also need: require 'facets/core/enumerable/sum' For fun, here's a one line version (more or less): require 'facets/more/functor' oc = Functor.new([h1,h2]){|s,m| m.map{|h| h[s]}} oc.rabbits.sum T.