Wann soll ich reduceLeft
, reduceRight
, foldLeft
, foldRight
, scanLeft
oder scanRight
?
Ich möchte eine Intuition / einen Überblick über ihre Unterschiede - möglicherweise mit einigen einfachen Beispielen.
scala
scala-collections
reduce
fold
Marc Grue
quelle
quelle
reduce
undfold
NICHT die Existenz eines Startwerts - vielmehr eine Folge eines tieferen mathematischen Grundes.Antworten:
Im Allgemeinen wenden alle 6-fach-Funktionen einen binären Operator auf jedes Element einer Sammlung an. Das Ergebnis jedes Schritts wird an den nächsten Schritt weitergegeben (als Eingabe für eines der beiden Argumente des Binäroperators). Auf diese Weise können wir ein Ergebnis kumulieren .
reduceLeft
undreduceRight
kumulieren ein einzelnes Ergebnis.foldLeft
undfoldRight
kumulieren Sie ein einzelnes Ergebnis mit einem Startwert.scanLeft
undscanRight
eine Sammlung von kumulativen Zwischenergebnissen unter Verwendung eines Startwerts kumulieren.Akkumulieren
Von LINKS und vorwärts ...
Mit einer Sammlung von Elementen
abc
und einem binären Operator könnenadd
wir untersuchen, was die verschiedenen Faltfunktionen tun, wenn Sie vom linken Element der Sammlung (von A nach C) vorwärts gehen:Von RECHTS und rückwärts ...
Wenn wir mit dem RIGHT-Element beginnen und rückwärts gehen (von C nach A), werden wir feststellen, dass jetzt das zweite Argument für unseren binären Operator das Ergebnis akkumuliert (der Operator ist der gleiche, wir haben nur die Argumentnamen geändert, um ihre Rollen zu verdeutlichen ):
.
Entkumulieren
Von LINKS und vorwärts ...
Wenn stattdessen waren wir de-kumulieren von dem Elemente LEFT einiges Ergebnis durch Subtraktion einer Sammlung beginnen, würden wir das Ergebnis durch das erste Argument kumulieren
res
unseren Binäroperatorsminus
:Von RECHTS und rückwärts ...
Aber achten Sie jetzt auf die xRight-Variationen! Denken Sie daran, dass der (de-) kumulierte Wert in den xRight-Variationen an den zweiten Parameter
res
unseres Binäroperators übergeben wirdminus
:Die letzte Liste (-2, 3, -1, 4, 0) ist vielleicht nicht das, was Sie intuitiv erwarten würden!
Wie Sie sehen, können Sie überprüfen, was Ihr foldX tut, indem Sie stattdessen einfach einen scanX ausführen und das kumulierte Ergebnis bei jedem Schritt debuggen.
Endeffekt
reduceLeft
oderreduceRight
.foldLeft
oderfoldRight
wenn Sie einen Startwert haben.Kumulieren Sie eine Sammlung von Zwischenergebnissen mit
scanLeft
oderscanRight
.Verwenden Sie eine xLeft-Variante, wenn Sie die Sammlung vorwärts durchgehen möchten .
quelle
List
und dann anzuwendenfoldLeft
. Andere Sammlungen können andere Strategien implementieren. WennfoldLeft
undfoldRight
kann austauschbar verwendet werden (assoziative Eigenschaft des angewendeten Operators),foldLeft
ist dies im Allgemeinen effizienter und vorzuziehen.Normalerweise funktioniert die Methode REDUCE, FOLD, SCAN, indem Daten auf LEFT gesammelt und die Variable RIGHT weiter geändert werden. Der Hauptunterschied zwischen ihnen ist REDUZIEREN, FALTEN ist: -
Das Falten beginnt immer mit einem
seed
Wert, dh einem benutzerdefinierten Startwert. Reduzieren löst eine Ausnahme aus, wenn die Sammlung leer ist, wobei Falte den Startwert zurückgibt. Wird immer einen einzelnen Wert ergeben.Der Scan wird für einige Verarbeitungsreihenfolgen von Elementen von links oder rechts verwendet. Anschließend können wir das vorherige Ergebnis für die nachfolgende Berechnung verwenden. Das heißt, wir können Elemente scannen. Wird immer eine Sammlung ergeben.
RIGHT_REDUCE steht im Gegensatz zu reductLeft one, dh es sammelt Werte in RIGHT und ändert die linke Variable weiter.
reductLeftOption und reduRightOption ähneln left_reduce und right_reduce. Der einzige Unterschied besteht darin, dass sie Ergebnisse im OPTION-Objekt zurückgeben.
Ein Teil der Ausgabe für den unten genannten Code wäre: -
Verwenden der
scan
Operation über eine Liste von Zahlen (Verwenden desseed
Werts0
)List(-2,-1,0,1,2)
{0, -2} => - 2 {-2, -1} => - 3 {-3,0} => - 3 {-3,1} => - 2 {-2,2} => 0 Scan-Liste (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) List ( 0, 2, 3, 3, 2, 0)
{2,0} => 2 {1,2} => 3 {0,3} => 3 {-1,3} => 2 {-2,2} => 0 scanRight (b + a) List ( 0, 2, 3, 3, 2, 0)
Verwendung
reduce
,fold
Operationen über eine Liste von StringsList("A","B","C","D","E")
Code:
quelle
Für die Sammlung x mit den Elementen x0, x1, x2, x3 und einer beliebigen Funktion f haben Sie Folgendes:
Abschließend
scan
ist wiefold
, gibt aber auch alle Zwischenwerte ausreduce
benötigt keinen Anfangswert, der manchmal etwas schwieriger zu finden istfold
braucht einen Anfangswert, der etwas schwerer zu finden ist: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
quelle