Вызывает ли использование метода Ruby 'push' удаление значения из исходного массива?


Я нашел следующий код в качестве решения проблемы новичка Ruby, включающей рандомизацию. Я понимаю, что у Ruby есть метод shuffle, однако цель моего вопроса заключается именно в push.

def shuffle arr
    shuf = []
    while arr.length > 0

        # Randomly pick one element of the array.
        rand_index = rand(arr.length)

        # Now go through each item in the array,
        # putting them all into new_arr except for the # randomly chosen one, which goes into shuf. 

        curr_index = 0
        new_arr = []
        arr.each do |item|
            if curr_index == rand_index
                shuf.push item
            else
                new_arr.push item
            end

            curr_index = curr_index + 1
        end

        # Replace the original array with the new, # smaller array.
        puts arr.inspect
        arr = new_arr
    end
    shuf
end

shuffle_array = [1,2,3,4,5,6,7,8,9]
shuffle(shuffle_array)

Вывод в командной строке был следующим:

Rick:programs rickthomas$ ruby shuffleSolution.rb
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 8, 9]
[1, 2, 3, 4, 5, 8, 9]
[1, 2, 3, 4, 5, 9]
[1, 2, 3, 4, 9]
[1, 3, 4, 9]
[3, 4, 9]
[3, 9]
[3]
Rick:programs rickthomas$ 

Судя по строке while arr.length > 0, похоже, что arr убывает постепенно, что, как я предполагаю, связано с pushing элементами из arr в любой из двух других массивов. Чтобы проверить это предположение, я возился с следующий код:

array1 = [1,2,3,4,5,6,7,8]
array2 = []
array3 = []
array1.each do |x|
  random_num = rand(2)
  if random_num == 1
    array2.push x
  else
    array3.push x
  end
  puts array1.inspect

end

Я ожидал, что array1 уменьшится аналогично методу shuffle выше, но вместо этого я получил следующее:

Rick:programs rickthomas$ ruby socratesWork.rb
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
Rick:programs rickthomas$ 

Почему push удаляет элементы массива в первом фрагменте, но не во втором? Я просто где-то упустил синтаксическую ошибку, или я неправильно понял что-то более фундаментальное о push?

Я уже искал Stack Overflow для ответа на этот вопрос, и не смог найти аналогичный вопрос, опубликованный еще. Я тоже проверил ruby-doc.org, но он говорил только о добавлении к массиву, а не о перемещении (?) элементы из одного массива в другой.

3   2  

3 ответа:

Ну, вы толкаете все элементы , кроме одного с соответствующим индексом в new_arr. Его размер уменьшается на единицу в каждой итерации.

Похоже, что вы заменяете свой массив на меньший массив на каждой итерации.

 # Replace the original array with the new, # smaller array.
    puts arr.inspect
    arr = new_arr

В первом фрагменте внутренний цикл разбивает исходный массив arr на 2 части:

  1. элемент, который соответствует случайному индексу, и он помещается в массив shuf
  2. те элементы, которые не соответствуют случайному индексу, они были помещены в new_arr, который инициализируется как пустой массив в каждом внешнем цикле.
Таким образом, в каждом внешнем цикле shuf получает еще один элемент, а new_arr получает все элементы в arr, кроме случайно выбранного. То магия выходит в последней строке внешнего цикла, где new_arr присваивается arr. Таким образом, каждый цикл arr становится на один элемент меньше. Это не магия или побочный эффект Array#push.