Как я могу использовать Array # delete во время итерации по массиву?

У меня есть массив, который я хочу перебрать и удалить некоторые элементы. Это не работает:

a = [1, 2, 3, 4, 5]
a.each do |x|
  next if x < 3
  a.delete x
  # do something with x
end
a #=> [1, 2, 4]

Я хочу a быть [1, 2]. Как я могу обойти это?

Ответ 1

a.delete_if { |x| x >= 3 }

См. документацию по методике здесь

Update:

Вы можете обрабатывать x в блоке:

a.delete_if do |element|
  if element >= 3
    do_something_with(element)
    true # Make sure the if statement returns true, so it gets marked for deletion
  end
end

Ответ 2

Вам не нужно удалять из массива, вы можете его фильтровать так:

a = [1, 2, 3, 4, 5]

b = a.select {|x| x < 3}

puts b.inspect # => [1,2]

b.each {|i| puts i} # do something to each here

Ответ 3

Я задал этот вопрос совсем недавно.

Удаление во время итерации в Ruby?

Он не работает, потому что Ruby завершает цикл .each при попытке удалить что-то. Если вы просто хотите удалить объекты из массива, delete_if будет работать, но если вы хотите большего контроля, то решение, которое у меня есть в этом потоке, работает, хотя оно вроде уродливо.

Ответ 4

Другой способ сделать это - использовать reject!, который, возможно, более ясен, поскольку имеет !, что означает "это изменит массив". Единственное отличие состоит в том, что reject! вернет nil, если никаких изменений не было.

a.delete_if {|x| x >= 3 }

или

a.reject! {|x| x >= 3 }

оба будут работать нормально.