data_arr = [['dog', 'Fido'], ['cat', 'Whiskers'], ['fish', 'Fluffy']]
data_hash = data_arr.inject({}) do |hsh, v|
hsh[v[0]] = v[1]
hsh
end
Hi, why do I not need to initialize data_hash as an empty hash? And why do I have to add hsh in the last line if not it will result in an error.
why do I not need to initialize
data_hash
as an empty hash?
You do, implicitly. The value passed to inject
, ie {}
will become the initial value for hsh
which will eventually become the value for data_hash
. According to the documentation :
At the end of the iteration, the final value of memo is the return value for the method.
Let's see what happens if we don't pass {}
:
If you do not explicitly specify an initial value for memo , then the first element of collection is used as the initial value of memo .
The first element of your collection is the array ['dog', 'Fido']
. If you omit {}
, then inject
would use that array as the initial value for hsh
. The subsequent call to hsh[v[0]] = v[1]
would fail, because of:
hsh = ['dog', 'Fido']
hsh['cat'] = 'Whiskers'
#=> TypeError: no implicit conversion of String into Integer
why do I have to add hsh in the last line
Again, let's check the documentation:
[...] the result [of the specified block] becomes the new value for memo .
inject
expects you to return the new value for hsh
at the end of the block.
if not it will result in an error.
That's because an assignment like hsh[v[0]] = v[1]
returns the assigned value, eg 'Fido'
. So if you omit the last line, 'Fido'
becomes the new value for hsh
:
hsh = 'Fido'
hsh['cat'] = 'Whiskers'
#=> IndexError: string not matched
There's also each_with_object
which works similar to inject
, but assumes that you want to mutate the same object within the block. It therefore doesn't require you to return it at the end of the block: (note that the argument order is reversed)
data_hash = data_arr.each_with_object({}) do |v, hsh|
hsh[v[0]] = v[1]
end
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}
or using array decomposition :
data_hash = data_arr.each_with_object({}) do |(k, v), hsh|
hsh[k] = v
end
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}
Although to convert your array to a hash you can simply use Array#to_h
, which is
[...] interpreting ary as an array of
[key, value]
pairs
data_arr.to_h
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.