From: Brian Candler Date: 2011-02-09T05:01:16+09:00 Subject: Re: making hash key from arrays botp wrote in post #980085: > just joining the fun here.. an inject version > > keys.zip(values).inject(Hash.new{|h,k|h[k]=[]}) {|hsh,(k,v)| > hsh.tap{|h|h[k] << v}} > #=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]} That's a prime example of using inject purely for obfuscation. The principal property of inject is that the value which is the output of one iteration is fed in as in input to the next iteration. You're not using that property here, because you're mutating the same object each time. In that case, it's just a complicated way of saying 'each'. You may as well just write: h = Hash.new { |h,k| h[k] = [] } keys.zip(values).each { |k,v| h[k] << v } h Furthermore, if you insist on using #tap, at least do it on the outside where it belongs in this case: Hash.new { |h,k| h[k] = [] }.tap do |hsh| keys.zip(values).each { |k,v| hsh[k] << v } end Now, if you wanted to do this in a functional way using inject, then you would mutate nothing and instead build a new Hash object in each iteration: keys.zip(values).inject({}) do |hsh,(k,v)| if hsh.has_key?(k) hsh.merge(k=>hsh[k]+[v]) else hsh.merge(k=>[v]) end end That, in my opinion, is the correct way to use inject here - and it's reasonably clear when written that way too. The Ruby runtime will end up doing a lot of hash copying though. Regards, Brian. -- Posted via http://www.ruby-forum.com/.