Background
Scalas Sammelvorgang ist cool, nicht wahr? Sie können ordentlich schreiben, ohne zusätzliche Zwischenvariablen zu erstellen.
Scala
val result = (0 to 10000)
.filter(_ % 3 == 0)
.map(_ + 1)
.groupBy(_ % 10)
.map { it =>
val k = it._1
val v = it._2.sum
(k, v)
}.toList
Dieser Code ist die Summe jeder Zahl, wenn die Zahlen von 0 bis 10000 als Vielfaches von 3 belassen und durch 1 geteilt und in Gruppen unterteilt werden. Diese Berechnung hat keine besondere Bedeutung, ist jedoch ein Beispiel, in dem der Datenverarbeitungsfluss auf sehr leicht verständliche (coole) Weise mit genau derselben Denkweise geschrieben werden kann.
Wenn ich das in Python versuche ...
Python
import itertools
result = range(0, 10001)
result = filter(lambda x: x % 3 == 0, result)
result = map(lambda x: x + 1, result)
result = map(lambda x: (x % 10, x), result)
result = sorted(result)
result = itertools.groupby(result, lambda x: x[0])
result = map(lambda x: (x[0], sum(map(lambda _: _[1], x[1]))), result)
result = list(result)
Es ist schwer zu sehen und ich kann es nicht einmal sehen. Übrigens, wenn Sie in einer Aufnahme schreiben, ohne Zwischenvariablen zu verwenden
Python
result = list(
map(lambda x: (x[0], sum(map(lambda _: _[1], x[1]))),
itertools.groupby(
sorted(
map(lambda x: (x % 10, x),
map(lambda x: x + 1,
filter(lambda x: x % 3 == 0,
range(0, 100001)
)
)
), lambda x: x[0]
)
)
)
)
Der Code mit 0 Lesbarkeit ist abgeschlossen. Sie können mit etwas aufwachen, wenn Sie dies reibungslos lesen können. Der Grund ist, dass Sie, wenn Sie in der Reihenfolge f-> g-> h verarbeiten möchten, in umgekehrter Reihenfolge wie h (g (f (x))) schreiben müssen.
Tatsächlich gibt es eine Bibliothek, die dies löst. Ja, mit toolz
, scalafunctional
und fn.py
. In diesem Artikel sind Meinungen wie ** Write in Scala ** NG-Wörter.
Toolz, CyToolz
toolz
ist eine Bibliothek, die Pythons integrierte itertools
und functools
erweitert, damit sie funktionaler geschrieben werden können. cytoolz
ist auch eine schnellere Version davon, die in Cython neu erstellt wurde. Die darin implementierten "Pipe" - und Curled-Funktionen sind sehr nützlich. Der schreckliche Code, den ich zuvor erwähnt habe, kann wie folgt geschrieben werden:
from cytoolz.curried import *
import operator as O
result = pipe(range(0, 10001),
filter(lambda x: x % 3 == 0),
map(lambda x: x + 1),
reduceby(lambda x: x % 10, O.add),
lambda d: d.items(),
list
)
Wie ist das? Geben Sie die Daten an, die Sie mit dem ersten Argument verarbeiten möchten, und geben Sie die Funktionen an, die Sie mit dem zweiten und den nachfolgenden Argumenten nacheinander anwenden möchten. Wenn Sie mit der R-Sprache vertraut sind, können Sie an dplyr
denken. Übrigens sind die hier verwendeten "Filter", "Karten" und "Reduzieren durch" alle Curry-Karten, und "Karte (f, Daten)" wird wie "Karte (f) (Daten)" multipliziert. Sie können mit "Rohr" wie folgt verbinden. Wenn Sie die gekräuselte Version nicht verwenden, ersetzen Sie pipe
durch thread_last
. Die von der vorherigen Funktion verarbeiteten Daten werden nacheinander an das letzte Argument jeder Funktion übergeben.
ScalaFunctional
Wie der Name schon sagt, ist scalafunctional
eine Bibliothek, mit der Sie die Scala-Sammlung ähnlich bedienen können. ~~ Wenn Sie so weit gehen möchten, fügen Sie Scala (ry ~~) hinzu. Fügen Sie in dieser Bibliothek list
, dict
usw. in eine dedizierte Klasse namens seq
ein und verarbeiten Sie sie in einer Punktkette.
from functional import seq
result = seq(range(0, 10001)) \
.filter(lambda x: x % 3 == 0) \
.map(lambda x: x + 1) \
.map(lambda x: (x % 10, x)) \
.reduce_by_key(O.add) \
.to_list()
Dies ist der Scala am nächsten. Python erfordert jedoch einen Backslash am Ende der Zeile, was etwas ärgerlich ist. Danach ist Pythons "Lambda" -Ausdruck nicht so flexibel wie die Scala-Funktion, daher kann es für eine komplizierte Verarbeitung erforderlich sein, die Funktion einmal zu "def". In jedem Fall ist es sehr einfach und schön.
fn.py
fn.py
ist auch eine Bibliothek für die funktionale Programmierung von Python. Das größte Merkmal ist, dass es wie ein Scala-Platzhalter geschrieben werden kann.
from fn import _
result = map(_ + 1, range(10))
Sie können es einfach anstelle von "Lambda" verwenden.
f = _ + 1
f(10)
>>>
11
Es passt gut zu toolz
und scalafunctional
.
toolz
result = pipe(range(10),
map(_ + 1),
list
)
scalafunctional
result = seq(range(10)) \
.map(_ + 1) \
.to_list()
Übrigens scheint in IPython usw. "_" nach der Reservierung zu stehen, um die letzte Ausgabe darzustellen. Wenn Sie es dort verwenden, müssen Sie es mit einem anderen Namen "importieren".
from fn import _ as it
Wenn Sie "toolz" und "scalafunctional" verwenden, wird die funktionale Programmierung auch in Python verbessert. scalafunctional
kann genau wie Scalas Erfassungsoperation geschrieben werden. Auf der anderen Seite können Sie "Pipe" von "Toolz" verwenden, um nicht nur Erfassungsvorgänge zu schreiben, sondern auch einen vielseitigeren Datenverarbeitungsfluss. Bitte kombinieren Sie diese gut mit fn.py
und genießen Sie Functional Python Life [^ pandas].
Alle diesmal verwendeten Bibliotheken werden auf GitHub veröffentlicht. Natürlich ist es auch in PyPI registriert, so dass Sie es mit pip
installieren können.
[^ pandas]: Selbst mit den Standard-Pandas ist es möglich, die Verarbeitung bis zu einem gewissen Grad mit einer Punktkette mit DataFrame zu verbinden.
Recommended Posts