Ich bin neu bei Scala und versuche herauszufinden, wie man am besten filtert & amp; Karte eine Sammlung. Hier ist ein Spielzeugbeispiel, um mein Problem zu erklären.
Vorgehensweise 1: Das ist ziemlich schlecht, da ich zweimal durch die Liste iteriere und in jeder Iteration den gleichen Wert erstelle.
%Vor% Ansatz 2: Das ist etwas besser, aber ich muss (x * x)
zweimal berechnen.
Ist es also möglich, dies zu berechnen, ohne zweimal durch die Sammlung zu gehen und die gleichen Berechnungen zu vermeiden?
Der typische Ansatz ist die Verwendung von iterator
(wenn möglich) oder view
(wenn iterator
nicht funktioniert). Dies vermeidet nicht genau zwei Traversals, vermeidet jedoch die Erstellung einer vollständigen Zwischenkollektion. Sie dann map
zuerst und filter
danach und dann map
erneut, falls erforderlich:
Der Vorteil dieses Ansatzes ist, dass er wirklich leicht zu lesen ist und da er keine Zwischensammlungen enthält, ist er ziemlich effizient.
Wenn Sie fragen, weil dies ein Leistungsengpass ist, lautet die Antwort normalerweise, eine tailrekursive Funktion zu schreiben oder die while-Schleifenmethode im alten Stil zu verwenden. Zum Beispiel in Ihrem Fall
%Vor% Sie können einen Parameter auch in inner
weiterleiten, anstatt einen externen Builder zu verwenden (besonders nützlich für Summen).
Sie können Sammeln , die eine Teilfunktion auf jeden Wert der Sammlung anwendet, für die sie definiert ist. Ihr Beispiel könnte folgendermaßen umgeschrieben werden:
%Vor%Betrachten Sie dies zum Verständnis,
%Vor% das entfaltet sich in einem flatMap
über dem Bereich und einem (faulen) withFilter
auf dem einmal berechneten Quadrat und liefert eine Sammlung mit gefilterten Ergebnissen. Es ist erforderlich, eine Iteration und eine Berechnung des Quadrats zu notieren (zusätzlich zum Erstellen des Bereichs).
Sie können flatMap
verwenden.
Oder mit Scalaz,
%Vor%Das löst die gestellte Frage, wie man das mit einer Iteration macht. Dies kann nützlich sein, wenn Daten wie mit einem Iterator gestreamt werden.
Allerdings ... wenn Sie stattdessen die absolute schnellste Implementierung wünschen, ist es das nicht. Tatsächlich vermute ich, dass Sie eine veränderbare ArrayList und eine while-Schleife verwenden würden. Aber erst nach dem Profiling würden Sie es sicher wissen. In jedem Fall ist das für eine andere Frage.
Die Verwendung eines für das Verständnis würde funktionieren:
%Vor%Ich bin mir auch nicht sicher, aber ich denke, der Scala-Compiler ist schlau über einen Filter vor einer Karte und macht nur einen Durchlauf, wenn möglich.
Tags und Links scala dictionary filter collections collect