Estoy tratando de eliminar números impares de una matriz.

arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]

def remove_odd_nums(arr)
  for x in arr
    if x % 2 == 0
      arr.delete(x)
    end
  end
end

print remove_odd_nums(arr)
# [1, 3, 5, 7, 10]

Parece que no puedo hacer que este programa funcione. El método funciona en los números, excepto el último. ¿Qué estoy haciendo mal?

1
Practical1 13 sep. 2018 a las 04:04

4 respuestas

La mejor respuesta

Desea eliminar números impares pero su programa está eliminando números pares (x % 2 == 0 verifica si x es un número par)

MÉTODO 1:

arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
arr.delete_if &:odd?

print arr

Delete_if itera incrementando el índice para arr, y elimina un elemento inmediatamente después de evaluar el bloque &:odd? con respecto al elemento. En otras palabras, está pasando por cada elemento de la matriz y eliminando el elemento si &:odd? es verdadero.

&:odd?: una función lambda que pasa un objeto al método odd?, que devuelve verdadero si el objeto es un número impar. Se pueden encontrar más explicaciones cuál es la funcionalidad del operador "&:" en rubí?

Tenga en cuenta que el método 1 en realidad MODIFICA la matriz original. Para una forma de crear una nueva matriz de números no impares, hay ...

MÉTODO 2:

non_odds = arr.select{|i| not i.odd?}
5
bunbun 13 sep. 2018 a las 09:25

Hola Practical1 solo para aclarar ¿por qué quieres destruir objetos y matriz?

En caso de que desee filtrar la matriz y solo seleccionar números even, puede probar una combinación de Array # select y Integer # even? ayudantes de método

    arr = arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    # select all even numbers in an array
    arr.select(&:even?) # shorthand for arr.select {|number| number.even? }

Devolverá números pares

[0] 2,
[1] 4,
[2] 6,
[3] 8,
[4] 10

Fuente:

Array # select https://apidock.com/ruby/Array/select

Entero # par? https://ruby-doc.org/core-1.8.7/Integer. html

2
Exwire 13 sep. 2018 a las 05:31

Ruby tiene métodos fabulosos para modificar arreglos en su lugar basados en la lógica en un bloque.

Para llegar a una matriz con solo números impares, puede eliminar los elementos que no cumplen con una prueba o mantener el número que sí cumple con una prueba. Puede devolver una nueva matriz o utilizar uno de los métodos de modificación en el lugar.

Para eliminar valores no deseados, use .reject para una nueva matriz o .reject! para modificar una matriz existente en su lugar.

Como estamos eliminando, usaríamos {|e| e%2!=0} dentro del bloque para números impares:

> [1,2,3,4,5,6,7,8,9,10].reject {|e| e%2!=0}
=> [2, 4, 6, 8, 10]                            # new array
> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.reject! {|e| e%2!=0}
=> [2, 4, 6, 8, 10]                            # arr modified in place

En lugar de un bloque, también puede usar la prueba lógica odd? para obtener el mismo resultado:

> [1,2,3,4,5,6,7,8,9,10].reject &:odd?
=> [2, 4, 6, 8, 10]

O bien, puede mantener los valores deseados y otros valores no se conservarán. Usaría {|e| e%2==0} dentro del bloque para valores pares. O puede usar &:even? en lugar del bloque.

Puede usar .keep_if para devolver un nueva matriz:

> arr
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> [1,2,3,4,5,6,7,8,9,10].keep_if {|e| e%2==0}
=> [2, 4, 6, 8, 10]                               # new array. 

O utilice .select! para modificar en el lugar:

> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.select! {|e| e%2==0}
=> [2, 4, 6, 8, 10]
> arr
=> [2, 4, 6, 8, 10]                                  # arr modified in place
2
dawg 13 sep. 2018 a las 15:42

TL; DR: no modifique una matriz mientras la itera.


Veamos qué sucede al imprimir el valor actual de x y arr dentro del bucle:

def remove_odd_nums(arr)
  for x in arr
    p x: x, arr: arr # <- debug output
    if x % 2 == 0
      arr.delete(x)
    end
  end
end

remove_odd_nums([1, 2, 3, 4, 5, 6, 7, 8, 10])

Salida:

{:x=>1, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>2, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>4, :arr=>[1, 3, 4, 5, 6, 7, 8, 10]}
{:x=>6, :arr=>[1, 3, 5, 6, 7, 8, 10]}
{:x=>8, :arr=>[1, 3, 5, 7, 8, 10]}

Los primeros dos valores x son los esperados: 1 y 2. Pero luego pasa a 4, omitiendo 3. También omite 5, 7 y 10. ¿Pero por qué?

Es porque está modificando la matriz mientras la itera. Piense en el bucle for como alguien que señala un elemento en una posición específica. Inicialmente se ve así:

1 2 3 4 5 6 7 8 10  <- array
^                   <- element

for luego pasa al siguiente elemento:

1 2 3 4 5 6 7 8 10
  ^

En este punto, x % 2 == 0 se vuelve verdadero y 2 se elimina de la matriz:

1 3 4 5 6 7 8 10
  ^

for no está al tanto de este cambio y simplemente pasa al siguiente elemento:

1 3 4 5 6 7 8 10
    ^

Por eso hemos omitido involuntariamente 3. Lo mismo sucede para 5 y 7.

Cuando for finalmente alcanza 8:

1 3 5 7 8 10
        ^

Se está borrando:

1 3 5 7 10
        ^

Y for detiene el bucle porque parece haber llegado al final de la matriz.

3
Stefan 13 sep. 2018 a las 07:30