Shane
Shane

Reputation: 5667

Converting an array into a hash

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

Answers (5)

DallaRosa
DallaRosa

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

Alok Anand
Alok Anand

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

BroiSatse
BroiSatse

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

Arup Rakshit
Arup Rakshit

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

Vapire
Vapire

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

Related Questions