Ruby push и удалить ошибку?

У меня есть этот код, и я не знаю, почему он не дает мне правильный ответ

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    list.push(n)
    a.delete(n)
  end
end 

p list => [1,2,4]
p a => [0,0,3]

Я не понимаю, почему номер не был добавлен в список. Когда я попытался использовать только "push", а не "a.delete", я получил правильные ответы

list = [1,2,3,4]
a = [0,0,2,3,4]

Что здесь происходит?

2 ответа

Решение

Внимательно посмотрите на вывод:

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    list.push(n)
    a.delete(n)
    p list,a
  end
end 

Выход:

[1, 2]
[0, 0, 3, 4]
[1, 2, 4]
[0, 0, 3]

Поэтому, когда ваш цикл удален 2, который был в 3-м пункте до удаления, 3 приходит в эту позицию. И когда цикл завершил обработку 3-го элемента, он перейдет к следующему элементу из коллекции, который будет равен 4. Это - то, как элемент 3 будет пропущен. Как и после удаления все ваши элементы будут смещены справа налево. Посмотрите ниже для большей ясности, чтобы увидеть, что происходит внутри цикла и состояние сбора a после каждого удаления.

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    p n
    i = a.find_index(n)
    list.push(n)
    a.delete(n)
    p a[i]
    p "-" *8
  end
end 

выход:

2
3
"--------"
4
nil
"--------"

Правило номер один для повторяющихся коллекций: не меняйте коллекцию, которую вы сейчас повторяете!,

Быстрое решение проблемы - перебрать копию коллекции.

list = [1] 
a = [0,0,2,3,4]

for n in a.dup # here, a copy
  if n!= 0
    list.push(n)
    a.delete(n)
  end
end 

list # => [1, 2, 3, 4]
a # => [0, 0]
Другие вопросы по тегам