2015-10-07 3 views
4

если я создаю этот массив:модификации двухмерный рубин массив

a = Array.new(3,Array.new(2,0)) 

он создает:

=> [[0, 0], [0, 0], [0, 0]] 

И когда я пытаюсь изменить конкретный элемент:

a[0][0] = 3 

он изменяет множественным значения:

=> [[3, 0], [3, 0], [3, 0]] 

Почему это происходит? И как я могу изменить определенный элемент?

ответ

6

Вы должны изменить, как вы инициализацию вашего Array (this is a known issue) к этому:

a = Array.new(3) { Array.new(2,0) } 

Разница между версией и этой версией является то, что Array.new(2,0) происходит только один раз. Вы создаете один массив с 3 «указателями» во второй массив. Это можно увидеть в следующем коде:

a = Array.new(3,Array.new(2,0)) 
a.map { |a| a.object_id } 
#=> [70246027840960, 70246027840960, 70246027840960] # Same object ids! 

a = Array.new(3) { Array.new(2,0) } 
a.map { |a| a.object_id } 
#=> [70246028007600, 70246028007580, 70246028007560] # Different object ids 
+0

Это нормально, если значение по умолчанию неизменно, равно как и Fixnum. Если 'a = Array.new (3) {Array.new (2, 'a')}', ('a' является изменяемым) и вы переназначаете элемент,' a [0] [0] = 'b'' , а не проблема: 'a # => [[" b "," a "], [" a "," a "], [" a "," a "]]'. Если, однако, вы * замените * элемент 'a [0] [0] .replace ('b')', вы получите '[[" b "," b "], [" a "," a " ], ["a", "a"]]. (Обязательно сначала повторите инициализацию 'a', если вы хотите проверить это.) Если вы используете' a = Array.new (3) {Array.new (2) {'a'}} ', тогда' a [0] [0] .Надеть ('B'); a # => [["b", "a"], ["a", "a"], ["a", "a"]] ', по желанию. Если вы не уверены, поместите значение по умолчанию в блок. –

4

Вам может понадобиться обратиться к this

Array.new(3,Array.new(2,0)) может быть понята в 2 этапа -

  1. новый массив Array.new(2,0) создается

  2. снова новый массив создается с помощью 3-х элементов с одним и тем же объектом (1) во всех трех местах.

Следовательно, изменение значения в любом из подмассивов изменяет значения в каждом из них. Суб-массивы относятся к одному и тому же объекту.

Как указал Гэвин Миллер, вам нужно будет использовать a = Array.new(3) { Array.new(2,0) }, чтобы изменить каждый элемент.

Смежные вопросы