Why is Array * referencing rather than copying values ​​in Ruby?

I want to duplicate the hash using the same keys but different values. I encoded the following snippet and ran into something I did not expect:

hsh = {:foo => 'foo', :bar => 'bar'}

hsh_copy = Hash[hsh.keys.zip([[]] * hsh.length)] # => {:foo=>[], :bar=>[]}
hsh_copy[:foo] << 1
hsh_copy[:bar] << 2

hsh_copy # => {:foo=>[1, 2], :bar=>[1, 2]}

It seems that instead of copying the nested array when using the operator, *it just continues to reference the first array.

I would be very happy if someone could explain why this is happening. Also, the best way to duplicate the hash will be appreciated, but I'm more interested in understanding why it *does not work as expected.

+3
source share
2 answers

Array#* , (, , ), .

, : hsh.keys.zip([[]] * hsh.length) hsh.map {|k,v| [k, []] }.

+3

* .

, , , , .

:

irb(main):012:0> ([[]] * 3).map { |e| e.object_id }

= > [2149128060, 2149128060, 2149128060]

.map Ruby [] , :

irb(main):013:0> ([[]] * 3).map { |e| e.clone.object_id }

= > [2149106700, 2149106660, 2149106640]

+1

Source: https://habr.com/ru/post/1781162/


All Articles