Einfache Frage, angesichts einer solchen Liste
%Vor%und nehme an, dass ich eine Funktion wie folgt definiert habe:
%Vor%Und ich möchte diese Funktion auf die Liste anwenden, also wenn ich
tippe %Vor%Dies ergibt
%Vor%Ich möchte, dass es als
herauskommt %Vor%so funktioniert es.
Was ist der beste Weg, dies zu tun? Angenommen, ich kann die Funktion foo [] Definition nicht ändern (sagen wir, es ist eingebaut)
Nur zwei Möglichkeiten, die ich jetzt kenne, sind
%Vor%(zu viel Arbeit) oder
%Vor%(weniger tippen, aber zuerst transponieren)
Frage: Gibt es noch andere bessere Möglichkeiten, um das oben genannte zu tun? Ich schaute auf andere Map und seine Freunde, und ich konnte keine Funktion sehen, um es direkter zu machen, als was ich habe.
Nur um rätselhafte Leistungstests der beiden Methoden zu melden ( @@@
, @@ # & /@
):
Diese Ergebnisse sind nicht zufällig, sondern in etwa proportional für sehr unterschiedliche Datengrößen.
@@@
ist ungefähr 3-4 mal schneller für Subtract
, Divide
, Power
, Log
und @@ # & /@
ist 4 mal schneller für Plus
und Times
, was zu weiteren Fragen führt , die (wie man glauben kann) leicht sein könnte
verdeutlicht durch folgende Bewertung:
Nur Plus
und Times
haben die Attribute Flat
und Orderless
, während unter anderem nur Power
(was dort relativ effizient erscheint) auch das Attribut OneIdentity
hat.
Bearbeiten
Eine zuverlässige Erklärung der beobachteten Leistungssteigerungen (dank Leonid Shifrins Ausführungen) sollte einen anderen Weg gehen.
Standardmäßig gibt es MapCompileLength -> 100
, da wir die Auswertung von SystemOptions["CompileOptions"]
prüfen können.
Um die Autokompilierung von Map zurückzusetzen, können wir Folgendes auswerten:
Nun können wir die relative Leistung der beiden Methoden testen, indem wir noch einmal unsere H
- Leistungstestfunktion für verwandte Symbole und Liste auswerten:
Mit diesen Ergebnissen können wir schlussfolgern, dass Yodas Ansatz ( @@@
) am effizientesten ist, während der von Andrei im Fall von Plus
und Times
aufgrund der automatischen Kompilierung von Map
erlaubt ist bessere Leistung von ( @@ # & /@
).
Ein paar weitere Möglichkeiten zur Auswahl:
Dieser ist eine ausführlichere Version von yodas Antwort. Sie wendet foo
nur auf Stufe 1 der Liste lst
an (ersetzt die Überschrift List
mit der Überschrift foo
):
Das macht dasselbe, aber bildet Apply
über der Liste lst
ab (im Wesentlichen Andreis Antwort):
Und das ersetzt einfach das Muster List [x__] mit foo [x] auf Level 1:
%Vor% Die Antworten auf Apply[]
sind genau richtig und das Richtige, aber was Sie versuchen wollten, war ein List[]
head durch ein Sequence[]
head zu ersetzen, dh List[List[3,5],List[6,7]]
sollte es werden List[Sequence[3,5],Sequence[6,7]]
.
Der Sequenzkopf bleibt natürlich, wenn ein Kopf einer Liste von Parametern gelöscht wird, also würden Delete[Plus[3,5],0]
und Delete[{3,5},0]
und Delete[List[3,5],0]
alle Sequence[3,5]
erzeugen.
So wird foo@Delete[#,0]&/@{{a, b}, {c, d}, {e, f}}
Ihnen dasselbe geben wie foo@@@{{a, b}, {c, d}, {e, f}}
.
Alternativ macht foo[#/.List->Sequence]&/@{{a, b}, {c, d}, {e, f}}
dasselbe.
Tags und Links wolfram-mathematica