Assume arr
is an array [[1,3],[2,5],[3,8]]
. I was wondering what *
means. What does it mean?
hash = Hash[*arr.flatten] # => {1=>3, 2=>5, 3=>8}
I tried the following
arr.flatten # => [1, 3, 2, 5, 3, 8]
Hash[arr.flatten] # => {}
Hash[*a.flatten] # => {1=>3, 2=>5, 3=>8}
Here is the explanation
When you do array.flatten
it will give you one flatten array where all inner array slatted. Now You are putting this flatten array inside the Hash::[]
method. But Hash::[]
supports the below constructs :
Hash[ key, value, ... ] → new_hash
# or
Hash[ [ [key, value], ... ] ] → new_hash
Now array.flatten
gives you [1, 3, 2, 5, 3, 8]
. Now you are putting this array inside Hash[]
like Hash[[1, 3, 2, 5, 3, 8]]
. Now compare with the above 2 structures. Does either of them match ? NO. So you need to splat the inner array again, thus it need (splatted operator)*
to splat the inner array.
Now you did Hash[*[1, 3, 2, 5, 3, 8]]
, which gives Hash[1, 3, 2, 5, 3, 8]
. Now again check from the above 2 constructs. Does it match with either of the 2 ? This time YES, first one. So you got the desired hash {1=>3, 2=>5, 3=>8}
.
BTW, you don't need to splat, as the second construt exactly matched when you put array inside Hash::[]
directly.
array = [[1,3],[2,5],[3,8]]
Hash[array] # => {1=>3, 2=>5, 3=>8}
The above worked, because Hash[array]
means Hash[[[1,3],[2,5],[3,8]]]
, which exactly the second structure as documentation suggested.
Read some examples to see how splatting work in Ruby.
There is another construct :-
Hash[ object ] → new_hash
This I think is also important to tell you why you got {}
. Hash[[1, 3, 2, 5, 3, 8]]
same as the last type of construct as per the doc. The doc is saying -
The second and third form take a single argument which is either an array of key-value pairs or an object convertible to a hash.
So. [1,3,2,5,3,8]
it is an Array
object not convertible to Hash
. Currently it is giving you an empty hash, if an object as per the third construct. But it will throw error in future version of release. See Below warnings.
[1] pry(main)> Hash[[1,2]]
(pry):1: warning: wrong element type Fixnum at 0 (expected array)
(pry):1: warning: ignoring wrong elements is deprecated, remove them explicitly
(pry):1: warning: this causes ArgumentError in the next release
(pry):1: warning: wrong element type Fixnum at 1 (expected array)
(pry):1: warning: ignoring wrong elements is deprecated, remove them explicitly
(pry):1: warning: this causes ArgumentError in the next release
=> {}
My Ruby version is :
ruby 2.0.0p451 (2014-02-24 revision 45167) [i686-linux]