¿Cómo puedo usar Array # delete mientras itero sobre el array?


Tengo una matriz que quiero iterar y eliminar algunos de los elementos. Esto no funciona:

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]

Quiero a ser [1, 2]. ¿Cómo puedo evitar esto?

Author: Christian Strempfer, 2010-07-16

4 answers

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

Véase la documentación del método aquí

Actualización:

Puedes manejar x en el bloque:

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
 105
Author: Chubas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 01:05:21

No tienes que borrar del array, puedes filtrarlo así:

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
 7
Author: Joc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-15 23:24:11

Hice esta pregunta no hace mucho.

¿Borrando Mientras se Itera en Ruby?

No funciona porque Ruby sale del bucle .each cuando intenta eliminar algo. Si simplemente quieres eliminar cosas de la matriz, delete_if funcionará, pero si quieres más control, la solución que tengo en ese hilo funciona, aunque es un poco desagradable.

 2
Author: Jesse Jashinsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:23

Otra forma de hacerlo es usando reject!, que es discutiblemente más claro ya que tiene un ! que significa "esto cambiará la matriz". La única diferencia es que reject! devolverá nil si no se hicieron cambios.

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

O

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

Ambos funcionarán bien.

 2
Author: AlexChaffee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-06 21:38:04