Scala: Die beste Methode zum Filtern und Zuordnen in einer Iteration

7

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.

%Vor%

Ist es also möglich, dies zu berechnen, ohne zweimal durch die Sammlung zu gehen und die gleichen Berechnungen zu vermeiden?

    
Can Bal 15.06.2015, 01:08
quelle

9 Antworten

7

Könnte ein foldRight

verwenden %Vor%

A foldLeft würde auch ein ähnliches Ziel erreichen, aber die resultierende Liste wäre in umgekehrter Reihenfolge (aufgrund der Assoziativität von foldLeft .

Alternativ, wenn Sie mit Scalaz spielen möchten

%Vor%     
adelbertc 15.06.2015 01:31
quelle
4

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:

%Vor%

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).

    
Rex Kerr 15.06.2015 01:29
quelle
3

Ein sehr einfacher Ansatz, der die Multiplikation nur einmal durchführt. Es ist auch faul, also wird Code nur bei Bedarf ausgeführt.

%Vor%

Schauen Sie hier nach den Unterschieden zwischen filter und withFilter .

    
marios 15.06.2015 01:33
quelle
2

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%     
Gavin Schulz 15.06.2015 01:17
quelle
2

Ich muss noch bestätigen, dass dies wirklich ein einziger Durchgang ist, aber:

%Vor%     
triggerNZ 15.06.2015 01:37
quelle
2

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).

    
elm 15.06.2015 04:20
quelle
0

Sie können flatMap verwenden.

%Vor%

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.

    
Paul Draper 15.06.2015 06:09
quelle
0

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.

    
Ramon J Romero y Vigil 15.06.2015 11:31
quelle
-2

Ich bin auch Anfänger habe es so gemacht

%Vor%     
gauri 14.03.2016 14:51
quelle