Изменение подмассива в блоке each
не является вашей проблемой, в этом нет ничего плохого. Ваша проблема в том, что ваш внешний массив map
иногда содержит несколько ссылок на один и тот же объект подмассива.
Учтите это:
>> x = [[1, 2, 1, 3, 4], [1, 2, 2, 3, 4], [1, 2, 2, 3, 4]]
>> x.each { |a| a << a[-1] }
=> [[1, 2, 1, 3, 4, 4], [1, 2, 2, 3, 4, 4], [1, 2, 2, 3, 4, 4]]
Результаты будут одинаковыми каждый раз. Но если у вас есть это:
>> gotcha = [1, 2, 1, 3, 4]
>> x = [[1, 2, 1, 3, 4], gotcha, gotcha]
>> x.each { |a| a << a[-1] }
=> [[1, 2, 1, 3, 4, 4], [1, 2, 1, 3, 4, 4, 4], [1, 2, 1, 3, 4, 4, 4]]
Тогда вы получите дополнительные конечные элементы, которые вы видели (каждый раз), потому что gotcha
изменяется дважды. x
во втором случае будет puts
таким же, как x
в первом случае, но они не совпадают.
Ваш Array#map
подход всегда работает, потому что это:
x + [x[-1]]
по существу копирует x
, а затем добавляет x[-1]
к этой копии, он вообще никогда не изменяет x
, поэтому поведение gotcha
сверху не произойдет.
Вы не можете уйти от указателей, даже когда они называются ссылками.