In Ruby, why does Array.new(size, object) create an array consisting of multiple references to the same object?
As mentioned in this answer, Array.new(size, object)
creates an array with size
refer开发者_开发问答ences to the same object
.
hash = Hash.new
a = Array.new(2, hash)
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"},{"cat"=>"feline"}]
a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"},{"cat"=>"Felix"}]
Why does Ruby do this, rather than doing a dup
or clone
of object
?
Because that's what the documentation says it does. Note that Hash.new
is only being called once, so of course there's only one Hash
If you want to create a new object for every element in the array, pass a block to the Array.new
method, and that block will be called for each new element:
>> a = Array.new(2) { Hash.new }
=> [{}, {}]
>> a[0]['cat'] = 'feline'
=> "feline"
>> a
=> [{"cat"=>"feline"}, {}]
>> a[1]['cat'] = 'Felix'
=> "Felix"
>> a
=> [{"cat"=>"feline"}, {"cat"=>"Felix"}]
For certain classes that can't be modified in-place (like Fixnum
s) the Array.new(X, object)
form works as expected and is probably more efficient (it just calls memfill
instead of rb_ary_store
and yield
ing to the block):
For more complicated objects you always have the block form (e.g. Array.new(5) { Hash.new }
).
*Edit:* Modified according to the comments. Sorry for the stupid example, I was tired when I wrote that.
I came up with this answer, very short and simple solution
c_hash = Hash.new
["a","b","c","d","e","f"].each do |o|
tmp = Hash.new
[1,2,3].map {|r| tmp[r] = Array.new}
c_hash[o] = tmp
end
c_hash['a'][1] << 10
p c_hash
精彩评论