Trans
2/6/2009 2:13:00 PM
On Jan 31, 2:49=A0pm, Roger Pack <rogerpack2...@gmail.com> 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 =3D [ [:a,1], [:b,2] ]
# a.to_h #=3D> { :a=3D>1, :b=3D>2 }
#
# When a mixed or multi-element accociative array
# is used, the result is as follows:
#
# a =3D [ [:a,1,2], [:b,2], [:c], :d ]
# a.to_h #=3D> { :a=3D>[1,2], :b=3D>2, :c=3D>nil, :d=3D>nil }
#
# If the fist entry of the subelements is the same, then
# the values will be merged using #concat.
#
# a =3D [ [:a,1,2], [:a,3], [:a,4], [:a], :a ]
# a.to_h #=3D> { :a=3D>[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 =3D [ [:a,1,2], [:b,3], [:c] ]
# a.to_h(true) #=3D> { :a=3D>[1,2], :b=3D>[3], :c=3D>[] }
#
# Setting the mode to +:splat+ will produce the same result
# as calling +Hash[*array]+.
#
# a =3D [:a,1,:b,2,:c]
# a.to_h:splat #=3D> { :a=3D>1, :b=3D>2, :c=3D>nil }
#
# Setting the mode to +:flat+ will produce the same result
# as calling +Hash[*array.flatten]+.
#
# a =3D [:a,1,[:b,2,:c]]
# a.to_h:flat #=3D> { :a=3D>1, :b=3D>2, :c=3D>nil }
def to_h(mode=3Dnil)
case mode
when :splat
a =3D dup
a << nil if a.size % 2 =3D=3D 1
Hash[*a]
when :flat
a =3D flatten
a << nil if a.size % 2 =3D=3D 1
Hash[*a]
when :array, True
h =3D {}
each do |k,*v|
h[k] ||=3D []
h[k].concat(v)
end
h
else
h =3D {}
each do |k,*v|
h[k] ||=3D []
h[k].concat(v)
end
h.each do |k,v|
h[k] =3D 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.