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
#reduce
siempre 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.