Articles

Entendiendo los métodos #inject / #reduce enumerable de Ruby en menos de 5 minutos

Para comenzar, este método toma una matriz y dos argumentos cuando se define. Esto puede ser visualizado como el siguiente:

.inject { |memo, value| 
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}

A la nota, la variablememo aquí se llama memo a pie por la memoria. Esta variable es esencial porque almacena los datos que desea que recuerde este método mientras atraviesa la matriz, pero se puede nombrar como desee, ya que es solo una variable.

Me referiré a él comomemo a lo largo de esta explicación.

memo se le puede dar un valor inicial, pero no es necesario que tenga uno. Si no se define un valor inicial, memo toma el primer valor de la matriz.

### The starting value for memo is 5
.inject(5) { |memo, value|
#more lines of code here
}
### The starting value for memo is 1 (first value of the array)
.reduce { |memo, value|
#more lines of code here
}
#inject#reducesiempre devolverá un único objeto de datos — los datos memo tiene al final. Dicho esto, memo debe cambiarse y devolverse a medida que se realiza el bucle, de lo contrario, se mantendrá en el mismo valor.

Ahora que tenemos la semántica, voy a ejecutar a través de algunos ejemplos para cuando me di #inject#reduce útil.

Ejemplo 1 :Usando # inject / # reduce para aplicar una operación numérica

La forma más común de usar este método es cuando se le da una matriz de enteros y tiene que aplicar una operación numérica en toda la matriz. En este ejemplo, voy a mostrar cómo encontrar la suma de una matriz completa.

#inject#reduce , se ilustra como ejemplo:

.reduce { |memo, value|
memo += value
} ## The following is to illustrate how this method was traversed
~> 1 += 2 #memo returns 3
~> 3 += 3 #memo returns 6
~> 6 += 4 #memo returns 10
~> 10 += 5 #memo returns 15#=> 15

Ya que esta es una bonita forma habitual de usar #inject#reduce , hay un método taquigráfico que usted puede utilizar si usted sólo desea aplicar una operación numérica a lo largo de su matriz que indica de la siguiente manera:

## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20

Ejemplo 2: Usando #inyectar/ #reducir encontrar la cadena más larga

Para este ejemplo, digamos que usted está dada una matriz de cadenas y usted tiene que encontrar la cadena más larga en la matriz.

Para este caso, #inject#reduce se mostrará así:

sentences = sentences.inject{ |memo, sentence| 
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"

Para romper este: Desde que no inicializar memo con un valor que va a tomar el primer objeto en la matriz, sentences en este ejemplo. Dentro de nuestro método tenemos una instrucción if que simplemente compara nuestra longitud memo con cada longitud sentence.

Esta instrucciónif es donde ocurre la magia: si un sentence es más largo que el almacenado en memo, reasignamos el memo a sentence; de lo contrario, solo devolvemos el mismo valor.

de Esta manera, nuestro memo valor actualizará constantemente con el tiemposentence y #inject#reduce devolverá ese memo variable en la final.

Si desea ver cada paso ilustrado, puede ejecutarlo en Repl.it para verlo por ti mismo.

sentences = sentences.inject { |memo, sentence|
puts "Memo length is: #{memo.length}\nSentence length is: #{sentence.length}"
if memo.length < sentence.length
puts "Our sentence is longer"
memo = sentence
else
puts "Our memo is longer"
memo
end
puts "Our memo is: #{memo}\n \n"
memo
}

Ejemplo # 3: Usando # inject / # reduce para encontrar el número más repetido en un array

Ahora que practicamos el uso de este método de diferentes maneras, hagamos un ejemplo similar. Supongamos que se le da una matriz aleatoria de números y desea encontrar qué número se repite más.

Para este caso, puede usar#inject#reduce como:

numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}

Ahora, esta lógica es similar a la que hicimos en el ejemplo 2, la única diferencia está en nuestra instrucción if, usamos #count en nuestra matriz inicial para encontrar y almacenar qué valor tiene un recuento mayor o igual. De esta manera se nos devuelve solo el número que tiene el mayor recuento al final.