¿Cuándo debo usar reduceLeft, reduceRight, foldLeft, foldRight, scanLefto 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

reduceyfoldNO 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.
reduceLeftyreduceRightacumular un solo resultado.foldLeftyfoldRightacumular un solo resultado utilizando un valor inicial.scanLeftyscanRightacumular una colección de resultados acumulativos intermedios utilizando un valor inicial.Acumular
De izquierda a derecha ...
Con una colección de elementos
abcy un operador binario,addpodemos 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
resde 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
resde 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
reduceLeftoreduceRight.foldLeftofoldRightsi tiene un valor inicial.Acumula una colección de resultados intermedios con
scanLeftoscanRight.Utilice una variación xLeft si quiere ir hacia delante a través de la colección.
fuente
Listpara luego aplicarfoldLeft. Otras colecciones pueden implementar diferentes estrategias. En general, sifoldLeftyfoldRightpuede usarse indistintamente (propiedad asociativa del operador aplicado), entoncesfoldLeftes 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
seedvalor, 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
scanoperación sobre una lista de números (usando elseedvalor0)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,foldlas 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
scanes comofoldpero también emite todos los valores intermediosreduceno necesita un valor inicial que a veces es un poco más difícil de encontrarfoldnecesita 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).lastfuente