Ok, dies ist eher eine Informatikfrage als eine Frage, die auf einer bestimmten Sprache basiert. Gibt es jedoch einen Unterschied zwischen einer Kartenoperation und einer Foreach-Operation? Oder sind es einfach unterschiedliche Namen für dasselbe?
Ok, dies ist eher eine Informatikfrage als eine Frage, die auf einer bestimmten Sprache basiert. Gibt es jedoch einen Unterschied zwischen einer Kartenoperation und einer Foreach-Operation? Oder sind es einfach unterschiedliche Namen für dasselbe?
Antworten:
Anders.
foreach iteriert über eine Liste und wendet auf jedes Listenmitglied eine Operation mit Nebenwirkungen an (z. B. Speichern jeder in der Datenbank).
map iteriert über eine Liste, transformiert jedes Mitglied dieser Liste und gibt eine andere Liste derselben Größe mit den transformierten Mitgliedern zurück (z. B. Konvertieren einer Liste von Zeichenfolgen in Großbuchstaben).
map
ist nicht in der Ausführung ihrer zugrundeliegenden Logik zur Folge haben, bis , wenn die erwartete transformierte Liste beschworen wird. Im Gegensatz dazu wird foreach
die Operation sofort berechnet.
Der wichtige Unterschied zwischen ihnen besteht darin, dass map
alle Ergebnisse in einer Sammlung zusammengefasst werden, während foreach
nichts zurückgegeben wird. map
wird normalerweise verwendet, wenn Sie eine Sammlung von Elementen mit einer Funktion transformieren möchten, während foreach
einfach eine Aktion für jedes Element ausgeführt wird.
Kurz gesagt, foreach
dient zum Anwenden einer Operation auf jedes Element einer Sammlung von Elementen, während map
zum Transformieren einer Sammlung in eine andere.
Es gibt zwei signifikante Unterschiede zwischen foreach
und map
.
foreach
hat keine konzeptionellen Einschränkungen für die Operation, die angewendet wird, außer vielleicht ein Element als Argument zu akzeptieren. Das heißt, die Operation kann nichts tun, kann eine Nebenwirkung haben, kann einen Wert zurückgeben oder kann keinen Wert zurückgeben. Allesforeach
tun müssen, ist, eine Sammlung von Elementen zu durchlaufen und die Operation auf jedes Element anzuwenden.
map
Auf der anderen Seite gibt es eine Einschränkung für die Operation: Sie erwartet, dass die Operation ein Element zurückgibt und wahrscheinlich auch ein Element als Argument akzeptiert. Die map
Operation durchläuft eine Sammlung von Elementen, wendet die Operation auf jedes Element an und speichert schließlich das Ergebnis jedes Aufrufs der Operation in einer anderen Sammlung. Mit anderen Worten, das map
transformiert eine Sammlung in eine andere.
foreach
arbeitet mit einer einzigen Sammlung von Elementen. Dies ist die Eingabesammlung.
map
arbeitet mit zwei Sammlungen von Elementen: der Eingabesammlung und der Ausgabesammlung.
Es ist kein Fehler, die beiden Algorithmen in Beziehung zu setzen: Tatsächlich können Sie die beiden Algorithmen hierarchisch anzeigen, wobei map
eine Spezialisierung von vorliegt foreach
. Das heißt, Sie können foreach
das Argument der Operation verwenden und transformieren und in eine andere Sammlung einfügen. Der foreach
Algorithmus ist also eine Abstraktion, eine Verallgemeinerung des map
Algorithmus. Da foreach
der Betrieb nicht eingeschränkt ist, können wir mit Sicherheit sagen, dass dies foreach
der einfachste Schleifenmechanismus auf dem Markt ist und alles kann, was eine Schleife tun kann. map
Wie auch andere, speziellere Algorithmen dienen der Ausdruckskraft: Wenn Sie eine Sammlung in eine andere abbilden (oder transformieren) möchten, ist Ihre Absicht bei Verwendung klarer map
als bei Verwendung foreach
.
Wir können diese Diskussion weiter ausdehnen und den copy
Algorithmus betrachten: eine Schleife, die eine Sammlung klont. Auch dieser Algorithmus ist eine Spezialisierung des foreach
Algorithmus. Sie können eine Operation definieren, die bei einem bestimmten Element dasselbe Element in eine andere Sammlung einfügt. Wenn Sie foreach
diese Operation verwenden, haben Sie den copy
Algorithmus tatsächlich ausgeführt, allerdings mit reduzierter Klarheit, Ausdruckskraft oder Aussagekraft. Gehen wir noch weiter: Wir können sagen, dass dies map
eine Spezialisierung von copy
, selbst eine Spezialisierung von ist foreach
. map
kann jedes der Elemente ändern, über die es iteriert. Wenn map
keines der Elemente geändert wird, werden lediglich die Elemente kopiert und verwendet Kopie verwendet würde die Absicht klarer ausdrücken.
Der foreach
Algorithmus selbst kann abhängig von der Sprache einen Rückgabewert haben oder nicht. Gibt in C ++ beispielsweise foreach
die ursprünglich empfangene Operation zurück. Die Idee ist, dass die Operation möglicherweise einen Status hat, und Sie möchten möglicherweise, dass diese Operation überprüft, wie sie sich über die Elemente entwickelt hat. map
kann auch einen Wert zurückgeben oder nicht. In C ++ transform
(das Äquivalent für map
hier) wird zufällig ein Iterator an das Ende des Ausgabecontainers (Sammlung) zurückgegeben. In Ruby ist der Rückgabewert von map
die Ausgabesequenz (Sammlung). Der Rückgabewert der Algorithmen ist also wirklich ein Implementierungsdetail. Ihre Wirkung kann oder kann nicht das sein, was sie zurückgeben.
.forEach()
die Implementierung .map()
finden Sie hier: stackoverflow.com/a/39159854/1524693
Array.protototype.map
Methode & Array.protototype.forEach
sind beide ziemlich ähnlich.Führen Sie den folgenden Code aus: http://labs.codecademy.com/bw1/6#:workspace
var arr = [1, 2, 3, 4, 5];
arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
console.log();
arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
Sie geben genau das gleiche Ergebnis.
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
Hier habe ich einfach das Ergebnis des Rückgabewerts aus den Methoden map und forEach zugewiesen.
var arr = [1, 2, 3, 4, 5];
var ar1 = arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar1);
console.log();
var ar2 = arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar2);
console.log();
Jetzt ist das Ergebnis etwas knifflig!
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
[ 1, 2, 3, 4, 5 ]
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
undefined
Array.prototype.map
gibt ein Array zurück, Array.prototype.forEach
tut es aber nicht. Sie können also das zurückgegebene Array innerhalb der an die Map-Methode übergebenen Rückruffunktion bearbeiten und dann zurückgeben.
Array.prototype.forEach
Geht nur durch das angegebene Array, damit Sie Ihre Arbeit erledigen können, während Sie durch das Array gehen.
Der sichtbarste Unterschied besteht darin, dass die Karte das Ergebnis in einer neuen Sammlung sammelt, während foreach nur für die Ausführung selbst durchgeführt wird.
Es gibt jedoch einige zusätzliche Annahmen: Da der 'Zweck' der Karte die neue Liste von Werten ist, spielt die Reihenfolge der Ausführung keine Rolle. In der Tat generieren einige Ausführungsumgebungen parallelen Code oder führen sogar Memoizing ein, um das Aufrufen wiederholter Werte oder Faulheit zu vermeiden, um das Aufrufen von Werten überhaupt zu vermeiden.
foreach hingegen wird speziell für die Nebenwirkungen genannt; Daher ist die Reihenfolge wichtig und kann normalerweise nicht parallelisiert werden.
Kurze Antwort: map
und forEach
sind anders. Auch informell gesehen map
ist eine strikte Obermenge von forEach
.
Lange Antwort: Lassen Sie uns zunächst eine einzeilige Beschreibung von forEach
und erstellen map
:
forEach
iteriert über alle Elemente und ruft die jeweils bereitgestellte Funktion auf.map
iteriert über alle Elemente, ruft die angegebene Funktion für jedes Element auf und erzeugt ein transformiertes Array, indem das Ergebnis jedes Funktionsaufrufs gespeichert wird.In vielen Sprachen forEach
wird oft nur genannteach
. In der folgenden Diskussion wird JavaScript nur als Referenz verwendet. Es könnte wirklich jede andere Sprache sein.
Lassen Sie uns nun jede dieser Funktionen verwenden.
forEach
:Aufgabe 1: Schreiben Sie eine Funktion printSquares
, die ein Array von Zahlen akzeptiert arr
und das Quadrat jedes Elements darin druckt.
Lösung 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:Aufgabe 2: Schreiben Sie eine Funktion selfDot
, die ein Array von Zahlen akzeptiert und ein Array arr
zurückgibt, in dem jedes Element das Quadrat des entsprechenden Elements in istarr
.
Nebenbei: Hier versuchen wir in Slang-Begriffen, das Eingabearray zu quadrieren. Formal ausgedrückt versuchen wir, das Punktprodukt mit sich selbst zu berechnen.
Lösung 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
eine Obermenge von forEach
?Sie können map
beide Aufgaben, Aufgabe 1 und Aufgabe 2 , lösen . Sie können forEach
die Aufgabe 2 jedoch nicht verwenden .
In Lösung 1 , wenn Sie einfach ersetzen forEach
durch map
, wird die Lösung noch gültig sein. In Lösung 2 wird Ihre zuvor funktionierende Lösung jedoch durch Ersetzen map
durch forEach
beschädigt.
forEach
in Bezug auf map
:Eine andere Möglichkeit, map
die Überlegenheit zu erkennen , ist die Umsetzung forEach
in Bezug auf map
. Da wir gute Programmierer sind, werden wir uns nicht der Verschmutzung von Namespaces hingeben. Wir werden unsere forEach
einfach anrufen each
.
Array.prototype.each = function (func) {
this.map(func);
};
Wenn Sie den prototype
Unsinn nicht mögen , können Sie loslegen:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
überhaupt?Die Antwort lautet Effizienz. Wenn Sie nicht daran interessiert sind, ein Array in ein anderes Array umzuwandeln, warum sollten Sie das transformierte Array berechnen? Nur um es wegzuwerfen? Natürlich nicht! Wenn Sie keine Transformation wünschen, sollten Sie keine Transformation durchführen.
Während Map zur Lösung von Aufgabe 1 verwendet werden kann , sollte dies wahrscheinlich nicht der Fall sein. Für jeden ist der richtige Kandidat dafür.
Obwohl ich der Antwort von @madlep weitgehend zustimme, möchte ich darauf hinweisen, dass dies map()
eine strikte Supermenge von ist forEach()
.
Ja, map()
wird normalerweise verwendet, um ein neues Array zu erstellen. Es kann jedoch auch verwendet werden, um das aktuelle Array zu ändern.
Hier ist ein Beispiel:
var a = [0, 1, 2, 3, 4], b = null;
b = a.map(function (x) { a[x] = 'What!!'; return x*x; });
console.log(b); // logs [0, 1, 4, 9, 16]
console.log(a); // logs ["What!!", "What!!", "What!!", "What!!", "What!!"]
Im obigen Beispiel a
wurde zweckmäßigerweise so eingestellt, dass a[i] === i
z i < a.length
. Trotzdem zeigt es die Kraft von map()
.
Hier ist die offizielle Beschreibung vonmap()
. Beachten Sie, dass dies map()
sogar das Array ändern kann, auf dem es aufgerufen wird! Hagelmap()
.
Hoffe das hat geholfen.
Bearbeitet am 10.11.2015: Ausarbeitung hinzugefügt.
map
Funktion hätte, aber nein forEach
; Könntest du nicht einfach nicht verwenden map
anstatt forEach
? Auf der anderen Seite, wenn eine Sprache forEach
aber nein hätte map
, müssten Sie Ihre eigene implementieren map
. Sie könnten nicht einfach forEach
anstelle von verwenden map
. Sag mir was du denkst.
Hier ist ein Beispiel in Scala mit Listen: Map gibt Liste zurück, foreach gibt nichts zurück.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Map gibt also die Liste zurück, die sich aus der Anwendung der Funktion f auf jedes Listenelement ergibt:
scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)
scala> list map (x => x * 2)
res0: List[Int] = List(2, 4, 6)
Foreach wendet nur f auf jedes Element an:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Wenn Sie insbesondere über Javascript sprechen, besteht der Unterschied darin, dass map
es sich dabei um eine Schleifenfunktion handeltforEach
es sich um einen Iterator handelt.
Verwenden map
Sie diese Option, wenn Sie auf jedes Mitglied der Liste eine Operation anwenden und die Ergebnisse als neue Liste zurückerhalten möchten, ohne die ursprüngliche Liste zu beeinflussen.
Verwenden forEach
Sie diese Option, wenn Sie anhand der einzelnen Elemente der Liste etwas tun möchten . Sie können der Seite beispielsweise Dinge hinzufügen. Im Wesentlichen ist es ideal, wenn Sie "Nebenwirkungen" wollen.
Andere Unterschiede: forEach
Gibt nichts zurück (da es sich wirklich um eine Kontrollflussfunktion handelt), und die übergebene Funktion erhält Verweise auf den Index und die gesamte Liste, während map die neue Liste zurückgibt und nur das aktuelle Element übergibt.
ForEach versucht, eine Funktion wie das Schreiben in db usw. auf jedes Element der RDD anzuwenden, ohne etwas zurückzugeben.
Aber das map()
wendet eine Funktion auf die Elemente von rdd an und gibt das rdd zurück. Wenn Sie also die folgende Methode ausführen, schlägt sie in Zeile 3 nicht fehl, aber beim Sammeln der Festplatte nach dem Anwenden von foreach schlägt sie fehl und es wird ein Fehler ausgegeben, der besagt
Datei "<stdin>", Zeile 5, in <Modul>
AttributeError: Das Objekt 'NoneType' hat kein Attribut 'collect'.
nums = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
num2 = nums.map(lambda x: x+2)
print ("num2",num2.collect())
num3 = nums.foreach(lambda x : x*x)
print ("num3",num3.collect())
Iterator[String]
von bekommescala.io.Source.fromFile("/home/me/file").getLines()
und mich darauf.foreach(s => ptintln(s))
bewerbe, aber es wird gleich danach leer. Zur gleichen Zeit, wenn ich mich darauf bewerbe.map(ptintln(_))
- es wird einfach leer und nichts wird gedruckt.