Quand dois - je utiliser reduceLeft
, reduceRight
, foldLeft
, foldRight
, scanLeft
ou scanRight
?
Je veux une intuition / un aperçu de leurs différences - éventuellement avec quelques exemples simples.
scala
scala-collections
reduce
fold
Marc Grue
la source
la source
reduce
etfold
n'est PAS l'existence d'une valeur de départ - c'est plutôt la conséquence d'une raison mathématique sous-jacente plus profonde.Réponses:
En général, les 6 fonctions fold appliquent un opérateur binaire à chaque élément d'une collection. Le résultat de chaque étape est passé à l'étape suivante (comme entrée de l'un des deux arguments de l'opérateur binaire). De cette façon, nous pouvons cumuler un résultat.
reduceLeft
etreduceRight
cumulez un seul résultat.foldLeft
etfoldRight
cumulez un seul résultat en utilisant une valeur de départ.scanLeft
etscanRight
cumulez une collection de résultats cumulatifs intermédiaires en utilisant une valeur de départ.Accumuler
De GAUCHE et vers l'avant ...
Avec une collection d'éléments
abc
et un opérateur binaire,add
nous pouvons explorer ce que font les différentes fonctions de repli lors du passage de l'élément LEFT de la collection (de A à C):De DROITE et en arrière ...
Si nous commençons par l'élément RIGHT et revenons en arrière (de C à A), nous remarquerons que maintenant le deuxième argument de notre opérateur binaire accumule le résultat (l'opérateur est le même, nous avons simplement changé les noms des arguments pour clarifier leurs rôles ):
.
De-cumuler
De GAUCHE et vers l'avant ...
Si à la place nous devions décumuler un résultat par soustraction à partir de l'élément LEFT d'une collection, nous cumulions le résultat via le premier argument
res
de notre opérateur binaireminus
:De DROITE et en arrière ...
Mais recherchez les variations xRight maintenant! Rappelez-vous que la valeur (dé-) cumulée dans les variations xRight est passée au deuxième paramètre
res
de notre opérateur binaireminus
:La dernière liste (-2, 3, -1, 4, 0) n'est peut-être pas ce à quoi vous vous attendriez intuitivement!
Comme vous le voyez, vous pouvez vérifier ce que fait votre foldX en exécutant simplement un scanX à la place et déboguer le résultat cumulé à chaque étape.
En bout de ligne
reduceLeft
oureduceRight
.foldLeft
oufoldRight
si vous avez une valeur de départ.Cumulez une collection de résultats intermédiaires avec
scanLeft
ouscanRight
.Utilisez une variation Xgauche si vous voulez aller en avant dans la collection.
la source
List
pour ensuite appliquerfoldLeft
. D'autres collections peuvent mettre en œuvre des stratégies différentes. En général, sifoldLeft
etfoldRight
peut être utilisé de manière interchangeable (propriété associative de l'opérateur appliqué), alorsfoldLeft
est plus efficace et préférable.Normalement, la méthode REDUCE, FOLD, SCAN fonctionne en accumulant des données sur LEFT et continuez à changer la variable RIGHT. La principale différence entre eux est REDUCE, FOLD est: -
Le pliage commencera toujours par une
seed
valeur, c'est-à-dire la valeur de départ définie par l'utilisateur. Réduire lèvera une exception si la collection est vide où as fold rendra la valeur de départ. Il en résultera toujours une valeur unique.La numérisation est utilisée pour un certain ordre de traitement des éléments du côté gauche ou droit, puis nous pouvons utiliser le résultat précédent dans le calcul ultérieur. Cela signifie que nous pouvons analyser les éléments. Il en résultera toujours une collection.
RIGHT_REDUCE est l'opposé de reductionLeft, c'est-à-dire qu'il accumule les valeurs dans RIGHT et continue de changer la variable de gauche.
reductionLeftOption et reductionRightOption sont similaires à left_reduce et right_reduce, la seule différence est qu'ils renvoient des résultats dans l'objet OPTION.
Une partie de la sortie pour le code mentionné ci-dessous serait: -
en utilisant l'
scan
opération sur une liste de nombres (en utilisant laseed
valeur0
)List(-2,-1,0,1,2)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 Liste de balayage (0, -2, -3, -3, -2, 0)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 scanLeft (a + b) Liste (0, -2, -3, -3, -2, 0)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 scanLeft (b + a) Liste (0, -2, -3, -3, -2, 0)
{2,0} => 2 {1,2} => 3 {0,3} => 3 {-1,3} => 2 {-2,2} => 0 scanRight (a + b) Liste ( 0, 2, 3, 3, 2, 0)
{2,0} => 2 {1,2} => 3 {0,3} => 3 {-1,3} => 2 {-2,2} => 0 scanRight (b + a) Liste ( 0, 2, 3, 3, 2, 0)
utilisation
reduce
,fold
opérations sur une liste de chaînesList("A","B","C","D","E")
Code:
la source
Pour la collection x avec les éléments x0, x1, x2, x3 et une fonction arbitraire f, vous avez les éléments suivants:
En conclusion
scan
est commefold
mais émet également toutes les valeurs intermédiairesreduce
n'a pas besoin d'une valeur initiale qui est parfois un peu plus difficile à trouverfold
a besoin d'une valeur initiale un peu plus difficile à trouver: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
la source