Reputation: 5667
Can anyone explain me how an array is converted into a Hash
here?
puts Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
I am not understanding what happens
behind when we call Hash[*[]]].flatten]
.
Upvotes: 0
Views: 128
Reputation: 5815
Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
The best thing we can do is to start from the inside and then go outwards.
In the innermost part you have two arrays that have two elements each: A symbol and a string.
Going for the next set of brackets, we have an array that contain those two arrays.
flatten
will flatten the two arrays inside, so that we have one array containg for elements, instead of an array containing another two arrays.
The star(*) operator, expands an array into a list of arguments to be used in a function.
So
[:first_name, 'Shane', :last_name, 'Harvie']
will turn into
:first_name, 'Shane', :last_name, 'Harvie'
the last part is Hash[]
which is a function that takes an array of parameters and turns them into a Hash.
{:first_name=>'Shane', :last_name=>'Harvie'}
Voila. It's simpler than it looked at first.
Observations:
If you take a look at the documentation of Hash, you'll see that you could have just passed multiple arrays to Hash[] and it would take care of it.
References:
Upvotes: 1
Reputation: 3356
What we get without using of splat * :--
[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
#=> [[:first_name, "Shane", :last_name, "Harvie"]]
So here you get a 2D array and '' => "".
Now, let's see what we get with splat * being used:--
[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
#=> [:first_name, "Shane", :last_name, "Harvie"]
Here you get 1D array, so splat has caused the inner array to come out of its container array.
So Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
is same to Hash[:first_name, "Shane", :last_name, "Harvie"]
#=> {:first_name=>"Shane", :last_name=>"Harvie"}
Upvotes: 1
Reputation: 44675
Hash
class defines a method []
. This methods takes any number of arguments, takes each pair and creates a new hash with first element of each pair being keys and the second element being a value. If you pass odd amount ov arguments, this will fail. Also it allows you to pass 2d array or any number of 2 element arrays.
Now you have 2d array: [[:first_name, 'Shane'], [:last_name, 'Harvie']]
. When you call flatten, you merge all the inner arrays in one:
Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
Hash[[:first_name, 'Shane', :last_name, 'Harvie']]
Now if you use splat operator, you extract all the elements and pass them to []
method as separate arguments, so this transaltes to:
Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
Hash[:first_name, 'Shane', :last_name, 'Harvie']
Note however that it is not needed - Hash[]
can deal with the initial form. Just do:
Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']]]
Upvotes: 2
Reputation: 118261
You just need to do :
Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']]]
# => {:first_name=>"Shane", :last_name=>"Harvie"}
Look at the documentation syntax :
Hash[ key, value, ... ] → new_hash
Hash[ [ [key, value], ... ] ] → new_hash
If you do use faltten
then below is the result :-
[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
# => [[:first_name, "Shane", :last_name, "Harvie"]]
If you do use splat with faltten
then you would get below :
[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
# => [:first_name, "Shane", :last_name, "Harvie"]
Now, Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten]
will give you the hash, as my top code gives. but you don't need to do this much work, as Hash
documentation clearly matches with your input data, so only Hash[input_data]
is enough.
Upvotes: 2
Reputation: 4578
First the array is flattened:
[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten
# becomes: [:first_name, 'Shane', :last_name, 'Harvie']
Since the Hash#[]
method accepts an arbitrary number of parameters like so
Hash['a', 'b', 'c', 'd']
and not an array you need to use the splat operator (*
) to expand the array on the stack so the values get used as parameters
Hash[*[:first_name, 'Shane', :last_name, 'Harvie']]
# becomes: Hash[:first_name, 'Shane', :last_name, 'Harvie']
And Arup is right, you don't need the flatten, because the Hash#[]
method accepts 2d arrays as well.
Upvotes: 1