2016-03-31 10 views
0

配列がデフォルトの文字列で埋められていて、デフォルトの文字列の文字の一部をランダムな位置に置き換えようとしています。配列要素の修正が正しく動作しない

私はこのような何かをした場合、私は配列のすべての要素が変更されています:

arr = ["*"] * 10 
arr[0][0..2] = "aaa" 
arr 
# => ["aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa"] 

しかし、私は別の方法で配列を初期化すると、それが動作:

(0..10).each.map {|i| arr[i] = "*"} 
arr[0][0..2] = "aaa" 
arr 
# => ["aaa", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"] 

一部more、initialize、すべての要素は同じです:

str = "*" 
(0..10).each.map {|i| arr[i] = str} 
arr[0][0..2] = "aaa" 
arr 
# => ["aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa"] 

代わりに、私はこれをユニークな要素で初期化しました:

str = "*" 
(0..10).each.map {|i| arr[i] = "#{str}" } 
arr[0][0..2] = "aaa" 
arr 
# => ["aaa", "*", "*", "*", "*", "*", "*", "*", "*", "*"] 

このような動作の背景は何ですか?

答えて

4

オブジェクトに配列ストア参照。そのように配列を初期化すると、同じ文字列への参照が10個ある配列が得られます。その後、文字列を変更します。コントラストについては

arr = ['*']*3 
# => ["*", "*", "*"] 
arr.map &:object_id 
# => [70305424624600, 70305424624600, 70305424624600] 

、このようルビーは、各要素の新しい文字列を割り当てます。

Array.new(3){ '*' }.map &:object_id 
# => [70184497001120, 70184497001060, 70184497001000] 
+0

は、組み込みの 'Array#new'オブジェクトコンストラクタがデフォルト値を扱うことができるので、使用する必要があります。 [ドキュメントを読む](http://ruby-doc.org/core-2.2.0/Array.html) – Charles

1

arr=["*"]*10を実行すると、まったく同じStringオブジェクトがすべてのアレイスロットに配置されます。一方、(0..10).each.map { |i| arr[i] = "*" }は配列内の各要素に対して新しいStringオブジェクトを作成しています。

次のコードで示さ:

(0..10).each.map { |i| arr[i] = "*" } 
arr[0].equal? arr[1] # Check if first and second elements point to same Object 
# => false 
arr = ["*"] * 10 
arr[0].equal? arr[1] 
# => true 
0
arr = ["*"]*10 

この文では、10個の要素の配列を作成しますが、これらすべての要素は、固有のものではなく、を参照してください。配列を塗りつぶす前に作成した文字列"*"の同じインスタンス。あなたは、アレイ内の任意の要素の値を変更するときに、あなたが実際にの値変数を変更します、配列のすべての要素が同じ文字列のインスタンスを参照してください

a = "*" 
arr = [a, a, a, a, a, a, a, a, a, a] 
#=> ["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"] 

arr.map(&:object_id) 
#=> [15424420, 15424420, 15424420, 15424420, 15424420, 15424420, 15424420, 15424420, 15424420, 15424420] 

:私はあなたのコードが同じであることを意味します、結果として、あなたは同じ配列が変数を埋めてしまいますので、その値が「AAA」に変更されたため、出力は次のようになります。あなたが埋める第二の例では

["aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa", "aaa"] 

それぞれの要素で配列の新しいインスタンスが"*"の文字列であるため、単一の配列値を変更すると、配列のこの具体的な要素にのみ影響し、他のすべての配列はメモリ内の異なる割り当てオブジェクトを参照するため、同じものになります。

arr = (0..10).each.map { |i| arr[i] = "*" } 
#=> ["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"] 
arr.map(&:object_id) 
#=> [14451520, 14451500, 14451480, 14451440, 14451420, 14451320, 14451300, 14451280, 14451260, 14451240, 14451160] 
+0

*これらの要素はすべてユニークではありません。 – sawa

+0

私は配列のすべての要素が値と参照によって互いに等しいことを意味します。したがって、それらは一意ではありません。 – SunnyMagadan

関連する問題