it-swarm.com.de

Gibt es einen Unterschied zwischen foreach und map?

Ok, das ist eher eine Frage der Informatik als eine Frage, die auf einer bestimmten Sprache basiert, aber gibt es einen Unterschied zwischen einer Kartenoperation und einer foreach-Operation? Oder sind es einfach unterschiedliche Namen für dasselbe Ding?

213
Robert Gould

Anders.

foreach durchläuft eine Liste und wendet auf jedes Listenmitglied eine Operation mit Nebenwirkungen an (z. B. das Speichern 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)

288
madlep

Der wichtige Unterschied zwischen ihnen ist, dass map alle Ergebnisse in einer Sammlung sammelt, während foreach nichts zurückgibt. map wird normalerweise verwendet, wenn Sie eine Auflistung von Elementen mit einer Funktion transformieren möchten, während foreach einfach eine Aktion für jedes Element ausführt.

119
Henk

Kurz gesagt, foreach dient zum Anwenden einer Operation auf jedes Element einer Elementauflistung, während map zum Umwandeln einer Auflistung in eine andere dient.

Es gibt zwei signifikante Unterschiede zwischen foreach und map.

  1. foreach hat keine konzeptionellen Einschränkungen für die anzuwendende Operation, außer möglicherweise ein Element als Argument zu akzeptieren. Das heißt, die Operation kann nichts tun, einen Nebeneffekt haben, einen Wert zurückgeben oder einen Wert nicht zurückgeben. Alles, was foreach interessiert, ist, eine Sammlung von Elementen zu durchlaufen und die Operation auf jedes Element anzuwenden.

    map hat andererseits eine Einschränkung für die Operation: Es erwartet, dass die Operation ein Element zurückgibt und wahrscheinlich auch ein Element als Argument akzeptiert. Die Operation map 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, die maptransformiert eine Sammlung in eine andere.

  2. foreach arbeitet mit einer einzelnen Sammlung von Elementen. Dies ist die Eingabeauflistung.

    map arbeitet mit zwei Elementauflistungen: der Eingabeauflistung und der Ausgabeauflistung.

Es ist kein Fehler, die beiden Algorithmen in Beziehung zu setzen: Tatsächlich können Sie die beiden hierarchisch anzeigen, wobei map eine Spezialisierung von foreach ist. Das heißt, Sie könnten foreach verwenden und die Operation ihr Argument transformieren und in eine andere Auflistung einfügen lassen. Der Algorithmus foreach ist also eine Abstraktion, eine Verallgemeinerung des Algorithmus map. Tatsächlich können wir, da foreach keine Einschränkung für seinen Betrieb hat, mit Sicherheit sagen, dass foreach der einfachste Schleifenmechanismus ist und alles kann, was eine Schleife kann. map sowie andere speziellere Algorithmen dienen der Aussagekraft: Wenn Sie eine Sammlung in eine andere abbilden (oder transformieren) möchten, ist Ihre Absicht klarer, wenn Sie map verwenden, als wenn Sie benutze foreach.

Wir können diese Diskussion weiter ausdehnen und den Algorithmus copy betrachten: eine Schleife, die eine Sammlung klont. Auch dieser Algorithmus ist eine Spezialisierung des Algorithmus foreach. Sie können eine Operation definieren, die bei einem bestimmten Element dasselbe Element in eine andere Auflistung einfügt. Wenn Sie foreach mit dieser Operation verwenden, haben Sie tatsächlich den copy -Algorithmus ausgeführt, wenn auch mit reduzierter Klarheit, Ausdruckskraft oder Eindeutigkeit. Lassen Sie es uns noch weiter gehen: Wir können sagen, dass map eine Spezialisierung von copy ist, selbst eine Spezialisierung von foreach. map darf ändern jedes der Elemente, über die iteriert wird. Wenn map keines der Elemente ändert, werden die Elemente lediglich kopiert und kopiert verwendet, um die Absicht klarer auszudrücken.

Der Algorithmus foreach selbst kann je nach Sprache einen Rückgabewert haben oder nicht. In C++ gibt 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. Auch map kann einen Wert zurückgeben oder nicht. In C++ gibt transform (hier das Äquivalent für map) einen Iterator an das Ende des Ausgabecontainers (Auflistung) zurück. 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 sein, was sie zurückgeben.

40
wilhelmtell

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

Aber die Wendung kommt, wenn Sie den folgenden Code ausführen:

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 schwierig!

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

Fazit

Array.prototype.map gibt ein Array zurück, aber Array.prototype.forEach nicht. Sie können also das zurückgegebene Array in der an die map-Methode übergebenen Rückruffunktion bearbeiten und dann zurückgeben.

Array.prototype.forEach durchläuft nur das angegebene Array, sodass Sie Ihre Aufgaben erledigen können, während Sie das Array durchlaufen.

31
abhisekp

Kurze Antwort:map und forEach sind unterschiedlich. Auch informell gesehen ist map eine strikte Obermenge von forEach.

Lange Antwort: Lassen Sie uns zuerst eine einzeilige Beschreibung von forEach und map erstellen:

  • forEach durchläuft alle Elemente und ruft für jedes die angegebene Funktion auf.
  • map durchläuft alle Elemente, ruft die angegebene Funktion für jedes Element auf und erstellt ein transformiertes Array, indem das Ergebnis jedes Funktionsaufrufs gespeichert wird.

In vielen Sprachen wird forEach oft nur each genannt. 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.

Mit forEach:

Aufgabe 1: Schreibe eine Funktion printSquares, die ein Array von Zahlen arr akzeptiert, und drucke das Quadrat jedes Elements darin.

Lösung 1:

var printSquares = function (arr) {
    arr.forEach(function (n) {
        console.log(n * n);
    });
};

Mit map:

Aufgabe 2: Schreiben Sie eine Funktion selfDot, die ein Array von Zahlen arr akzeptiert und ein Array zurückgibt, in dem jedes Element das Quadrat des entsprechenden Elements in ist arr.

Nebenbei: Hier versuchen wir in der Umgangssprache, das Eingabearray zu quadrieren. Formal ausgedrückt versuchen wir, das Skalarprodukt mit sich selbst zu berechnen.

Lösung 2:

var selfDot = function (arr) {
    return arr.map(function (n) {
        return n * n;
    });
};

Wie ist map eine Obermenge von forEach?

Sie können map verwenden, um beide Aufgaben zu lösen, Aufgabe 1 und Aufgabe 2. Sie können jedoch nicht forEach verwenden, um die Aufgabe 2 zu lösen.

Wenn Sie in Lösung 1 einfach forEach durch map ersetzen, ist die Lösung weiterhin gültig. In Lösung 2 führt das Ersetzen von map durch forEach jedoch zu einer Störung Ihrer zuvor funktionierenden Lösung.

Implementieren von forEach in Form von map:

Eine andere Möglichkeit, die Überlegenheit von map zu realisieren, besteht darin, forEach in map zu implementieren. Da wir gute Programmierer sind, werden wir uns nicht der Namensraumverschmutzung hingeben. Wir nennen unser forEach, nur each.

Array.prototype.each = function (func) {
    this.map(func);
};

Nun, wenn Ihnen der Unsinn prototype nicht gefällt, können Sie loslegen:

var each = function (arr, func) {
    arr.map(func); // Or map(arr, func);
};

Also, ähm ... Warum gibt es überhaupt forEach?

Die Antwort lautet Effizienz. Wenn Sie nicht daran interessiert sind, ein Array in ein anderes Array zu transformieren, warum sollten Sie das transformierte Array berechnen? Nur um es loszuwerden? Natürlich nicht! Wenn Sie keine Transformation wünschen, sollten Sie keine Transformation durchführen.

So, während Karte verwendet werden kann, um Aufgabe 1 zu lösen, sollte es wahrscheinlich nicht. Für jeden ist das der richtige Kandidat.


Ursprüngliche Antwort:

Obwohl ich der Antwort von @madlep weitgehend zustimme, möchte ich darauf hinweisen, dass map() eine strenge Übermenge von forEach() ist.

Ja, map() wird normalerweise zum Erstellen eines neuen Arrays verwendet. Es kann jedoch also 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 wurde a zweckmäßigerweise so eingestellt, dass a[i] === i Für i < a.length Steht. Trotzdem demonstriert es die Kraft von map().

Hier ist die offizielle Beschreibung von map() . Beachten Sie, dass map() sogar das Array ändern kann, auf dem es aufgerufen wird! Gegrüßet seist du map().

Hoffe das hat geholfen.


Bearbeitet am 10.11.2015: Ausarbeitung hinzugefügt.

11
Sumukh Barve

der sichtbarste Unterschied ist, dass map das Ergebnis in einer neuen Sammlung sammelt, während foreach nur für die Ausführung selbst durchgeführt wird.

es gibt jedoch ein paar zusätzliche Annahmen: Da der 'Zweck' von map die neue Liste von Werten ist, spielt es keine Rolle, in welcher Reihenfolge sie ausgeführt werden. Tatsächlich generieren einige Ausführungsumgebungen parallelen Code oder führen sogar ein Memoizing ein, um das Aufrufen wiederholter Werte oder Faulheit zu vermeiden, um das Aufrufen einiger überhaupt zu vermeiden.

foreach wird andererseits speziell für die Nebenwirkungen aufgerufen; Daher ist die Reihenfolge wichtig und kann normalerweise nicht parallelisiert werden.

11
Javier

Hier ist ein Beispiel in Scala using lists: map gibt list 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 f nur auf jedes Element an:

scala> var sum = 0
sum: Int = 0

scala> list foreach (sum += _)

scala> sum
res2: Int = 6 // res1 is empty
3
irudyak

Wenn Sie insbesondere über Javascript sprechen, besteht der Unterschied darin, dass map eine Schleifenfunktion ist, während forEach ein Iterator ist.

Verwenden Sie map, wenn Sie eine Operation auf jedes Mitglied der Liste anwenden und die Ergebnisse als neue Liste erhalten möchten, ohne die ursprüngliche Liste zu beeinflussen.

Verwenden Sie forEach, wenn Sie do basierend auf jedem Element der Liste etwas tun möchten. Sie könnten der Seite beispielsweise Dinge hinzufügen. Im Wesentlichen ist es ideal, wenn Sie "Nebenwirkungen" möchten.

Weitere 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, wohingegen map die neue Liste zurückgibt und nur die aktuelle übergibt Element.

2
phyzome

ForEach versucht, auf jedes RDD-Element eine Funktion wie das Schreiben in db etc anzuwenden, ohne etwas zurückzugeben.

Aber die Funktion map() wendet eine Funktion auf die Elemente von rdd an und gibt die rdd zurück. Wenn Sie also die folgende Methode ausführen, schlägt sie in Zeile 3 nicht fehl, aber wenn Sie die rdd nach dem Anwenden von foreach sammeln, schlägt sie fehl und wirft einen Fehler, der besagt

Datei "<stdin>", Zeile 5, in <module>

AttributeError: 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())
0
user2456047