¿Cuándo debo usar reduceLeft
, reduceRight
, foldLeft
, foldRight
, scanLeft
o scanRight
?
Quiero una intuición / visión general de sus diferencias, posiblemente con algunos ejemplos simples.
scala
scala-collections
reduce
fold
Marc Grue
fuente
fuente
reduce
yfold
NO es la existencia de un valor inicial, sino que es consecuencia de una razón matemática subyacente más profunda.Respuestas:
En general, las 6 funciones de plegado aplican un operador binario a cada elemento de una colección. El resultado de cada paso se pasa al siguiente paso (como entrada a uno de los dos argumentos del operador binario). De esta manera podemos acumular un resultado.
reduceLeft
yreduceRight
acumular un solo resultado.foldLeft
yfoldRight
acumular un solo resultado utilizando un valor inicial.scanLeft
yscanRight
acumular una colección de resultados acumulativos intermedios utilizando un valor inicial.Acumular
De izquierda a derecha ...
Con una colección de elementos
abc
y un operador binario,add
podemos explorar lo que hacen las diferentes funciones de plegado al avanzar desde el elemento IZQUIERDO de la colección (de A a C):Desde la DERECHA y hacia atrás ...
Si comenzamos con el elemento DERECHO y retrocedemos (de C a A), notaremos que ahora el segundo argumento para nuestro operador binario acumula el resultado (el operador es el mismo, solo cambiamos los nombres de los argumentos para aclarar sus roles ):
.
Desacumular
De izquierda a derecha ...
Si, en cambio, dejáramos de acumular algún resultado restando a partir del elemento IZQUIERDO de una colección, acumularíamos el resultado a través del primer argumento
res
de nuestro operador binariominus
:Desde la DERECHA y hacia atrás ...
¡Pero busque las variaciones de xRight ahora! Recuerde que el valor (des) acumulado en las variaciones xRight se pasa al segundo parámetro
res
de nuestro operador binariominus
:¡La última Lista (-2, 3, -1, 4, 0) tal vez no sea lo que intuitivamente esperaría!
Como puede ver, puede verificar qué está haciendo su foldX simplemente ejecutando un scanX en su lugar y depurar el resultado acumulado en cada paso.
Línea de fondo
reduceLeft
oreduceRight
.foldLeft
ofoldRight
si tiene un valor inicial.Acumula una colección de resultados intermedios con
scanLeft
oscanRight
.Utilice una variación xLeft si quiere ir hacia delante a través de la colección.
fuente
List
para luego aplicarfoldLeft
. Otras colecciones pueden implementar diferentes estrategias. En general, sifoldLeft
yfoldRight
puede usarse indistintamente (propiedad asociativa del operador aplicado), entoncesfoldLeft
es más eficiente y preferible.Normalmente, el método REDUCE, FOLD, SCAN funciona acumulando datos en IZQUIERDA y sigue cambiando la variable DERECHA. La principal diferencia entre ellos es REDUCIR, PLEGAR es: -
Fold siempre comenzará con un
seed
valor, es decir, un valor inicial definido por el usuario. Reducir arrojará una excepción si la colección está vacía donde el pliegue devuelve el valor inicial. Siempre dará como resultado un único valor.El escaneo se usa para el orden de procesamiento de artículos desde el lado izquierdo o derecho, luego podemos hacer uso del resultado anterior en el cálculo posterior. Eso significa que podemos escanear artículos. Siempre resultará una colección.
RIGHT_REDUCE es opuesto a reducirLeft one, es decir, acumula valores en RIGHT y sigue cambiando la variable izquierda.
reduceLeftOption y reduceRightOption son similares a left_reduce y right_reduce, la única diferencia es que devuelven resultados en el objeto OPTION.
Una parte de la salida para el código mencionado a continuación sería: -
usando la
scan
operación sobre una lista de números (usando elseed
valor0
)List(-2,-1,0,1,2)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 Lista de escaneo (0, -2, -3, -3, -2, 0)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 scanLeft (a + b) Lista (0, -2, -3, -3, -2, 0)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 scanLeft (b + a) Lista (0, -2, -3, -3, -2, 0)
{2,0} => 2 {1,2} => 3 {0,3} => 3 {-1,3} => 2 {-2,2} => 0 scanRight (a + b) Lista ( 0, 2, 3, 3, 2, 0)
{2,0} => 2 {1,2} => 3 {0,3} => 3 {-1,3} => 2 {-2,2} => 0 scanRight (b + a) Lista ( 0, 2, 3, 3, 2, 0)
utilizando
reduce
,fold
las operaciones a través de una lista de cadenasList("A","B","C","D","E")
Código:
fuente
Para la colección x con elementos x0, x1, x2, x3 y una función arbitraria f tiene lo siguiente:
En conclusión
scan
es comofold
pero también emite todos los valores intermediosreduce
no necesita un valor inicial que a veces es un poco más difícil de encontrarfold
necesita un valor inicial que sea un poco más difícil de encontrar:x.reduceLeft(f) === x.drop(1).foldLeft(x.head,f)
x.foldRight(init,f) === x.reverse.foldLeft(init,f)
x.foldLeft(init,f) === x.scanLeft(init,f).last
fuente