Quando devo usar reduceLeft
, reduceRight
, foldLeft
, foldRight
, scanLeft
ou scanRight
?
Quero uma intuição / visão geral de suas diferenças - possivelmente com alguns exemplos simples.
scala
scala-collections
reduce
fold
Marc Grue
fonte
fonte
reduce
efold
NÃO é a existência de um valor inicial - é uma consequência de uma razão matemática subjacente mais profunda.Respostas:
Em geral, todas as funções de 6 dobras aplicam um operador binário a cada elemento de uma coleção. O resultado de cada etapa é passado para a próxima etapa (como entrada para um dos dois argumentos do operador binário). Dessa forma, podemos acumular um resultado.
reduceLeft
ereduceRight
acumule um único resultado.foldLeft
efoldRight
acumule um único resultado usando um valor inicial.scanLeft
escanRight
acumule uma coleção de resultados cumulativos intermediários usando um valor inicial.Acumular
Da esquerda para a frente ...
Com uma coleção de elementos
abc
e um operador binárioadd
, podemos explorar o que as diferentes funções de dobra fazem ao avançar do elemento LEFT da coleção (de A a C):À DIREITA e para trás ...
Se começarmos com o elemento RIGHT e voltarmos (de C para A), perceberemos que agora o segundo argumento para nosso operador binário acumula o resultado (o operador é o mesmo, apenas trocamos os nomes dos argumentos para deixar suas funções claras ):
.
De-acumular
Da esquerda para a frente ...
Se, em vez disso, deduzirmos algum resultado por subtração a partir do elemento LEFT de uma coleção, acumularemos o resultado através do primeiro argumento
res
do nosso operador bináriominus
:À DIREITA e para trás ...
Mas esteja atento às variações do xRight agora! Lembre-se de que o valor (des-) acumulado nas variações xRight é passado para o segundo parâmetro
res
do nosso operador bináriominus
:A última lista (-2, 3, -1, 4, 0) talvez não seja o que você esperaria intuitivamente!
Como você vê, você pode verificar o que o seu foldX está fazendo, basta executar um scanX e depurar o resultado acumulado a cada etapa.
Bottom line
reduceLeft
oureduceRight
.foldLeft
oufoldRight
se você tiver um valor inicial.Acumule uma coleção de resultados intermediários com
scanLeft
ouscanRight
.Use uma variação do xLeft se desejar avançar pela coleção.
fonte
List
aplicação entãofoldLeft
. Outras coleções podem implementar estratégias diferentes. Em geral, sefoldLeft
efoldRight
pode ser usado de forma intercambiável (propriedade associativa do operador aplicado), entãofoldLeft
é mais eficiente e preferível.Normalmente, o método REDUCE, FOLD, SCAN funciona acumulando dados em ESQUERDA e continua alterando a variável RIGHT. A principal diferença entre eles é REDUCE, FOLD é: -
A dobra sempre começará com um
seed
valor, ou seja, um valor inicial definido pelo usuário. Reduzir lançará uma exceção se a coleção estiver vazia, onde, como dobra, devolve o valor inicial. Sempre resultará em um único valor.A digitalização é usada para alguma ordem de processamento de itens do lado esquerdo ou direito, para que possamos usar o resultado anterior no cálculo subsequente. Isso significa que podemos digitalizar itens. Sempre resultará em uma coleção.
RIGHT_REDUCE é o oposto de reduzir à esquerda, isto é, ele acumula valores em RIGHT e continua alterando a variável esquerda.
reduzirLeftOption e reduzirRightOption são semelhantes a left_reduce e right_reduce. A única diferença é que retornam resultados no objeto OPTION.
Uma parte da saída do código abaixo mencionado seria: -
usando
scan
operação sobre uma lista de números (usandoseed
valor0
)List(-2,-1,0,1,2)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 Lista de varredura (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)
usando
reduce
,fold
operações sobre uma lista de StringsList("A","B","C","D","E")
Código:
fonte
Para a coleção x com os elementos x0, x1, x2, x3 e uma função arbitrária f, você tem o seguinte:
Em conclusão
scan
é como,fold
mas também emite todos os valores intermediáriosreduce
não precisa de um valor inicial que às vezes é um pouco mais difícil de encontrarfold
precisa de um valor inicial um pouco mais 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
fonte