I have a hash, whose values are an array of size 1
:
hash = {:start => [1]}
I want to unpack the arrays as in:
hash.each_pair{ |key, value| hash[key] = value[0] } # => {:start=>1}
and I thought the *
-operator as in the following would work, but it does not give the expected result:
hash.each_pair{ |key, value| hash[key] = *value } # => {:start=>[1]}
Why does *value
return [1]
and not 1
?
Because the []=
method applied to hash
takes only one argument in addition to the key (which is put inside the []
part), and a splatted/expanded array, which is in general a sequence of values (which coincidentally happens to be a single element in this particular case) cannot be directly accepted as the argument as is splatted. So it is accepted by the argument of []=
as an array after all.
In other words, an argument (of the []=
method) must be an object, but splatted elements (such as :foo, :bar, :baz
) are not an object. The only way to interpret them as an object is to put them back into an array (such as [:foo, :bar, :baz]
).
Using the splat operator, you can do it like this:
hash.each_pair{|key, value| hash.[]= key, *value}