From: Benoit Daloze Date: 2010-12-12T23:42:34+09:00 Subject: [ruby-core:33686] Re: [feature:trunk] Enumerable#categorize On 12 December 2010 12:13, Tanaka Akira wrote: > Hi. > > How about a method for converting enumerable to hash? > > �enum.categorize([opts]) {|elt| [key1, ..., val] } -> hash > > categorizes the elements in _enum_ and returns a hash. > > The block is called for each elements in _enum_. > The block should return an array which contains > one or more keys and one value. > > �p (0..10).categorize {|e| [e % 3, e % 5] } > �#=> {0=>[0, 3, 1, 4], 1=>[1, 4, 2, 0], 2=>[2, 0, 3]} I find this clearer (but categorize looks better) : (0..10).group_by { |e| e%3 }.each_with_object({}) { |(k,v),h| h[k] = v.map { |e| e%5 } } (Unfortunately, the 'map' on a Hash is not very nice, so I guess you better 'group' by hand and 'map' at the same time like Martin showed) > Martin: I admit that it is more elegant if the initialization and the final line can be avoided, but I think that's an issue that can be dealt with separately. Enumerable#each_with_object is handy in this case: (0..10).each_with_object({}) { |e,h| (h[e%3] ||= []) << e%5 } Or, with Ryan's variant: (0..10).each_with_object(Hash.new { |h,k| h[k]=[] }) { |e,h| h[e%3] << e%5 } # I wish there was a shorter way for a self-duplicating Hash's default value For the rest, I agree with Martin. Regards, B.D.