I want to have a hash whose key is a string and the value is an array. I tried it the following way:
h = Hash.new([]) # => {}
h["one"] # => []
h["two"] # => []
h["one"].push 1 # => [1]
h["one"] # => [1]
h["two"] # => [1] //why did it assign it to h["two"] also??
What is the correct way to do it?
You get this behavior because []
that you passed into new
method isn't copied but referenced in all unset hash keys. So h['one']
references the same object as h['two']
. So if you modify object referenced by h['one']
(using push
method), h['two']
will also be modified.
The correct way to set default value which will be initialized for every single hash key is to use block:
h = Hash.new { |hash, key| hash[key] = [] }
I usually do it like this:
h = Hash.new { |h,k| h[k] = [] }
h['one']
h
# => { 'one' => [] }
h['two'] << 12
h
# => { 'one' => [], 'two' => [12] }
Which is more verbose and (IMO) reads nicer.
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.