From: Trans Date: 2009-02-06T23:12:39+09:00 Subject: Re: Array#to_h On Jan 31, 2:49 pm, Roger Pack wrote: > Not that I would find it useful at all, but is there is a Hash#to_a > should there not be an Array#to_h? The variety of possible good definitions make this hard to define. So it's understandable that is is not in Ruby core, though being able to convert back and forth between Hash#to_a and Array#to_h makes the most sense. I was thinking about it some more and I was thinking about how the various options might be addressed. So I came up with this: # Converts an associative array into a hash. # # a = [ [:a,1], [:b,2] ] # a.to_h #=> { :a=>1, :b=>2 } # # When a mixed or multi-element accociative array # is used, the result is as follows: # # a = [ [:a,1,2], [:b,2], [:c], :d ] # a.to_h #=> { :a=>[1,2], :b=>2, :c=>nil, :d=>nil } # # If the fist entry of the subelements is the same, then # the values will be merged using #concat. # # a = [ [:a,1,2], [:a,3], [:a,4], [:a], :a ] # a.to_h #=> { :a=>[1,2,3,4,nil,nil] } # # The +mode+ can be set to effect the result. If it is # set to +:array+ or +true+ then trailing arrays # will be kept. Eg. # # a = [ [:a,1,2], [:b,3], [:c] ] # a.to_h(true) #=> { :a=>[1,2], :b=>[3], :c=>[] } # # Setting the mode to +:splat+ will produce the same result # as calling +Hash[*array]+. # # a = [:a,1,:b,2,:c] # a.to_h:splat #=> { :a=>1, :b=>2, :c=>nil } # # Setting the mode to +:flat+ will produce the same result # as calling +Hash[*array.flatten]+. # # a = [:a,1,[:b,2,:c]] # a.to_h:flat #=> { :a=>1, :b=>2, :c=>nil } def to_h(mode=nil) case mode when :splat a = dup a << nil if a.size % 2 == 1 Hash[*a] when :flat a = flatten a << nil if a.size % 2 == 1 Hash[*a] when :array, True h = {} each do |k,*v| h[k] ||= [] h[k].concat(v) end h else h = {} each do |k,*v| h[k] ||= [] h[k].concat(v) end h.each do |k,v| h[k] = v[0] if v.size < 2 end h end end By using a +mode+ we can offer a variety of common means of conversion. Of course, we could just make them all separate methods, ie. #to_h, #to_h_array, #to_h_splat, #to_h_flat. Maybe that is better? But then that seems a bit more limiting, less dynamic, less open for new modes or multiple labels for a single mode, and the method names look funny (imo). Thoughts? T.