Изменение одного массива в массиве массивов изменяет их все;Зачем? - PullRequest
0 голосов
/ 23 марта 2012
a = Array.new(3,[])
a[1][0] = 5
a => [[5], [5], [5]]

Я думал, что это не имеет смысла! не так ли => [[], [5], []] или это особенность Руби?

1 Ответ

4 голосов
/ 23 марта 2012

Используйте это вместо:

a = Array.new(3){ [] }

В вашем коде один и тот же объект используется для значения каждой записи;как только вы мутируете одну из ссылок, вы видите, что все остальные меняютсяС учетом вышеизложенного вы вместо этого вызываете блок каждый раз, когда требуется новое значение, которое возвращает новый массив каждый раз .


Это по своей природе похоже на новоевопрос пользователя о том, почему следующее не работает должным образом:

str.gsub /(<([a-z]+)>/, "-->#{$1}<--"

В приведенном выше примере интерполяция строк происходит до того, как метод gsub когда-либо вызывается, поэтому он не может использоватьтекущее значение $1 в вашей строке.Аналогично, в вашем вопросе вы создаете объект и передаете его Array.new до того, как Ruby начнет создавать слоты массивов.Да, среда выполнения может вызывать dup для элемента по умолчанию ... но это может быть пагубным и медленным.Следовательно, вы получаете блочную форму, чтобы самостоятельно определить, как создавать начальные значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...