0

両方のコードが同じものを印刷しないのはなぜですか。私は最初の作品が2番目の作品の出力を生み出すことを意図していました

a=Array.new(5,Array.new(3))
for i in (0...a[0].length)
  a[0][i]=2
end
p a

#これは[[2、2、2]、[2、2、2]、[2、2、2]、[2、2、2]、[2、2、2]]*を出力します

a=Array.new(5).map{|d|d=Array.new(3)}
for i in (0...a[0].length)
  a[0][i]=2
end
p a

#これは[[2、2、2]、[nil、nil、nil]、[nil、nil、nil]、[nil、nil、nil]、[nil、nil、nil]]を出力します

4

3 に答える 3

3

これです

a=Array.new(5,Array.new(3))

同じ配列オブジェクトを含む配列を5回作成します。これを行うようなものです:

a = []
b = a
a[0] = 123
puts b[0] #=> 123

これはどこ:

a=Array.new(5).map{ Array.new(3) }

親配列のアイテムごとに新しい3アイテム配列を作成します。したがって、最初のアイテムを変更しても、他のアイテムには影響しません。

Arrayこれは、コンストラクタのデフォルト引数を実際に使用すべきではない理由でもありますHash。これらは常に期待どおりに機能するとは限らないためです。

于 2012-08-10T02:49:14.407 に答える
1

以下は同等です。

Array.new(5,Array.new(3))

[Array.new(3)] * 5

inside = Array.new(3); [inside, inside, inside, inside, inside]

それらはすべて、同じ配列を含む配列を生成します。私はまったく同じオブジェクトを意味します。そのため、その内容を変更すると、その新しい値が5回表示されます。

独立した配列が必要なため、「内部」配列が同じオブジェクトではないことを確認する必要があります。これは、さまざまな方法で実現できます。たとえば、次のようになります。

Array.new(5){ Array.new(3) }

5.times.map { Array.new(3) }

Array.new(5).map { Array.new(3) }

# or dup your array manually:
inside = Array.new(3); [inside.dup, inside.dup, inside.dup, inside.dup, inside]

Array.new(5, [])最初に使用したフォームはコピーされないことに注意してくださいobj。再利用されます。それはあなたが望むものではないので、あなたはブロックを5回呼び出すブロックフォームArray.new(5){ [] }を使うべきです、そしてそのたびに新しい配列が作成されます。

このHashクラスには2つのコンストラクターもあり、さらに注意が必要です。

于 2012-08-10T14:37:35.067 に答える
1
Array.new(5,Array.new(3))

最初の例では、配列に同じ配列への5つの参照が含まれています。を使用して配列の単一インスタンスを作成します。このインスタンスArray.new(3)への参照は、初期化する5つの配列のそれぞれに使用されます。を変更すると、、などa[0][0]も変更されます。これらはすべて同じ配列への参照です。a[1][0]a[2][0]

Array.new(5).map{ |d| Array.new(3) }

2番目の例では、配列に5つの異なる配列が含まれています。ブロックは5回呼び出され、5回Array.new(3)呼び出され、5つの異なる配列が作成されます。a[0]などとは異なる配列ですa[1]

于 2012-08-10T02:46:30.030 に答える