在Ruby中,为什么Array.new(size,object)创建一个由对同一对象的多个引用组成的数组?

时间:2011-01-09 22:52:56

标签: ruby arrays

正如this answer中所述,Array.new(size, object)创建了一个对同一size 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"}] 的数组。

dup

为什么Ruby会这样做,而不是clone的{​​{1}}或object

3 个答案:

答案 0 :(得分:9)

因为这是the documentation所说的。请注意Hash.new只被调用一次,所以当然只有一个Hash

如果要为数组中的每个元素创建一个新对象,请将块传递给Array.new方法,并为每个新元素调用该块:

>> a = Array.new(2) { Hash.new }
=> [{}, {}]
>> a[0]['cat'] = 'feline'
=> "feline"
>> a
=> [{"cat"=>"feline"}, {}]
>> a[1]['cat'] = 'Felix'
=> "Felix"
>> a
=> [{"cat"=>"feline"}, {"cat"=>"Felix"}]

答案 1 :(得分:2)

对于某些无法就地修改的类(如Fixnum s),Array.new(X, object)表单按预期工作,可能更有效(它只调用memfill而不是rb_ary_storeyield到街区):

对于更复杂的对象,您始终拥有阻止形式(例如Array.new(5) { Hash.new })。

* 编辑:*根据评论进行修改。抱歉这个愚蠢的例子,我写这篇文章的时候累了。

答案 2 :(得分:0)

我想出了这个答案,非常简短的解决方案

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