Ok, c’est plus une question d’informatique qu’une question basée sur une langue particulière, mais existe-t-il une différence entre une opération de carte et une opération de foreach? Ou sont-ils simplement des noms différents pour la même chose?
Différent.
foreach effectue une itération sur une liste et applique une opération avec des effets secondaires à chaque membre de la liste (par exemple, en enregistrant chaque élément dans la base de données)
map itère sur une liste, transforme chaque membre de cette liste et renvoie une autre liste de même taille avec les membres transformés (telle que la conversion d'une liste de chaînes en majuscules)
La différence importante entre eux est que map
accumule tous les résultats dans une collection, alors que foreach
ne renvoie rien. map
est généralement utilisé lorsque vous souhaitez transformer une collection d'éléments avec une fonction, alors que foreach
exécute simplement une action pour chaque élément.
En bref, foreach
sert à appliquer une opération sur chaque élément d’une collection d’éléments, tandis que map
sert à transformer une collection en une autre.
Il y a deux différences significatives entre foreach
et map
.
foreach
n'a pas de restrictions conceptuelles sur l'opération appliquée, à part peut-être accepter un élément comme argument. En d'autres termes, l'opération peut ne rien faire, avoir un effet secondaire, renvoyer une valeur ou ne pas renvoyer de valeur. Tout ce que foreach
veut, c’est de parcourir une collection d’éléments et d’appliquer l’opération sur chaque élément.
map
, d'autre part, a une restriction sur l'opération: elle s'attend à ce que l'opération renvoie un élément et accepte probablement également un élément en tant qu'argument. L'opération map
effectue une itération sur une collection d'éléments, applique l'opération à chaque élément et stocke le résultat de chaque appel de l'opération dans une autre collection. En d'autres termes, le map
transforme une collection en une autre.
foreach
fonctionne avec une seule collection d'éléments. Ceci est la collection d'entrée.
map
fonctionne avec deux collections d'éléments: la collection d'entrée et la collection de sortie.
Ce n'est pas une erreur de relier les deux algorithmes: en fait, vous pouvez afficher les deux hiérarchiquement, où map
est une spécialisation de foreach
. Autrement dit, vous pouvez utiliser foreach
et demander à l'opération de transformer son argument et de l'insérer dans une autre collection. Ainsi, l'algorithme foreach
est une abstraction, une généralisation de l'algorithme map
. En fait, étant donné que foreach
ne comporte aucune restriction quant à son fonctionnement, nous pouvons dire en toute sécurité que foreach
est le mécanisme de boucle le plus simple disponible et qu'il peut faire tout ce qu'une boucle peut faire. map
, ainsi que d’autres algorithmes plus spécialisés, existe-t-il pour l’expression: si vous souhaitez mapper (ou transformer) une collection en une autre, votre intention est plus claire si vous utilisez map
que si vous utilisez foreach
.
Nous pouvons approfondir cette discussion en considérant l'algorithme copy
: une boucle qui clone une collection. Cet algorithme est aussi une spécialisation de l'algorithme foreach
. Vous pouvez définir une opération qui, à partir d'un élément, insérera ce même élément dans une autre collection. Si vous utilisez foreach
avec cette opération, vous utiliserez effectivement l'algorithme copy
, avec toutefois une clarté, une expressivité ou une explicité réduite. Allons encore plus loin: nous pouvons dire que map
est une spécialisation de copy
, elle-même une spécialisation de foreach
. map
may change n'importe lequel des éléments sur lesquels il est itéré. Si map
ne change aucun élément, il ne fait que copier les éléments, et utiliser copier exprimerait plus clairement l'intention.
L'algorithme foreach
peut lui-même ou non avoir une valeur de retour, en fonction de la langue. En C++, par exemple, foreach
renvoie l'opération reçue à l'origine. L'idée est que l'opération peut avoir un état, et vous voudrez peut-être qu'elle revienne pour examiner son évolution au fil des éléments. map
peut également ou non renvoyer une valeur. En C++, transform
(l'équivalent de map
ici) renvoie un itérateur à la fin du conteneur de sortie (collection). En Ruby, la valeur de retour de map
est la séquence de sortie (collection). Ainsi, la valeur de retour des algorithmes est vraiment un détail d'implémentation; leur effet peut être ou ne pas être ce qu'ils retournent.
Array.protototype.map
méthode & Array.protototype.forEach
sont très similaires.Exécutez le code suivant: 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));
});
Ils donnent le résultat idem exact.
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
Ici, j'ai simplement assigné le résultat de la valeur de retour de la carte et des méthodes forEach.
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();
Maintenant, le résultat est quelque chose de délicat!
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
renvoie un tableau mais Array.prototype.forEach
ne le fait pas. Vous pouvez donc manipuler le tableau renvoyé dans la fonction de rappel transmise à la méthode map, puis le renvoyer.
Array.prototype.forEach
ne fait que parcourir le tableau donné afin que vous puissiez effectuer vos tâches tout en parcourant le tableau.
Réponse courte: map
et forEach
sont différents. De manière informelle, map
est un sur-ensemble strict de forEach
.
Réponse longue: Tout d'abord, décrivons une description en une ligne de forEach
et map
:
forEach
itère sur tous les éléments, appelant la fonction fournie sur chacun d'eux.map
itère sur tous les éléments, en appelant la fonction fournie sur chacun d'eux, et produit un tableau transformé en se souvenant du résultat de chaque appel de fonction.Dans de nombreuses langues, forEach
est souvent appelé simplement each
. La discussion suivante utilise JavaScript uniquement à titre de référence. Cela pourrait vraiment être n'importe quelle autre langue.
Maintenant, utilisons chacune de ces fonctions.
forEach
: Tâche 1: Ecrivez une fonction printSquares
, qui accepte un tableau de nombres arr
et affiche le carré de chaque élément en elle.
Solution 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
: Tâche 2: Ecrivez une fonction selfDot
, qui accepte un tableau de nombres arr
et renvoie un tableau dans lequel chaque élément est le carré de l'élément correspondant dans arr
.
De côté: ici, en termes d'argot, nous essayons de mettre en carré le tableau d'entrée. Formellement, nous essayons de calculer son produit scalaire avec lui-même.
Solution 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
est-il un sur-ensemble de forEach
?Vous pouvez utiliser map
pour résoudre les deux tâches, Tâche 1 et Tâche 2 . Cependant, vous ne pouvez pas utiliser forEach
pour résoudre la tâche 2 .
Dans Solution 1 , si vous remplacez simplement forEach
par map
, la solution sera toujours valide. Dans Solution 2 , toutefois, remplacer map
par forEach
rompra votre solution qui fonctionnait auparavant.
forEach
en termes de map
:Une autre façon de réaliser la supériorité de map
consiste à implémenter forEach
en termes de map
. En tant que bons programmeurs, nous ne nous livrerons pas à la pollution des espaces de noms. Nous appellerons notre forEach
, juste each
.
Array.prototype.each = function (func) {
this.map(func);
};
Maintenant, si vous n'aimez pas le non-sens prototype
, voici:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
existe-t-il même?La réponse est l'efficacité. Si vous n'êtes pas intéressé par la transformation d'un tableau en un autre tableau, pourquoi devriez-vous calculer le tableau transformé? Seulement pour le vider? Bien sûr que non! Si vous ne voulez pas de transformation, vous ne devriez pas faire de transformation.
Ainsi, alors que map peut être utilisé pour résoudre la tâche 1 , il ne devrait probablement pas. Pour chacun est le bon candidat pour cela.
Bien que je sois largement d’accord avec la réponse de @madlep, je voudrais souligner que map()
est un super-ensemble strict de forEach()
.
Oui, map()
est généralement utilisé pour créer un nouveau tableau. Cependant, il peut également être utilisé pour changer le tableau actuel.
Voici un exemple:
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!!"]
Dans l'exemple ci-dessus, a
a été défini de manière pratique, de sorte que a[i] === i
Pour i < a.length
. Même dans ce cas, il démontre le pouvoir de map()
.
Voici la description officielle de map()
. Notez que map()
peut même changer le tableau sur lequel il est appelé! Salut map()
.
J'espère que cela a aidé.
Édité le 10 novembre 2015: Ajout de l’élaboration.
la différence la plus "visible" est que la carte accumule le résultat dans une nouvelle collection, tandis que foreach ne concerne que l'exécution elle-même.
mais il y a quelques hypothèses supplémentaires: puisque le "but" de map est la nouvelle liste de valeurs, l'ordre d'exécution n'est pas important. En fait, certains environnements d’exécution génèrent du code parallèle, voire introduisent des mémos pour éviter d’appeler des valeurs répétées, ou lazyness, pour éviter d’en appeler du tout.
foreach, en revanche, est appelé spécifiquement pour les effets secondaires; par conséquent, l'ordre est important et ne peut généralement pas être mis en parallèle.
Voici un exemple dans Scala en utilisant des listes: map renvoie liste, foreach ne renvoie rien.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Donc, map renvoie la liste résultant de l'application de la fonction f à chaque élément de la liste:
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 applique simplement f à chaque élément:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Si vous parlez de Javascript en particulier, la différence est que map
est une fonction de boucle alors que forEach
est un itérateur.
Utilisez map
lorsque vous souhaitez appliquer une opération à chaque membre de la liste et récupérer les résultats sous forme de nouvelle liste, sans affecter la liste d'origine.
Utilisez forEach
lorsque vous voulez faire quelque chose à partir de chaque élément de la liste. Vous pourriez ajouter des éléments à la page, par exemple. Pour l’essentiel, c’est génial lorsque vous voulez des "effets secondaires".
Autres différences: forEach
ne renvoie rien (puisqu'il s'agit en réalité d'une fonction de flux de contrôle), et la fonction transmise obtient des références à l'index et à la liste entière, tandis que map renvoie la nouvelle liste et ne transmet que la liste en cours. élément.
ForEach essaie d'appliquer une fonction telle que l'écriture à db etc. sur chaque élément du RDD sans rien retourner en retour.
Mais la map()
applique une fonction sur les éléments de rdd et renvoie le rdd. Ainsi, lorsque vous exécutez la méthode ci-dessous, elle n'échouera pas sur line3, mais lors de la collecte du fichier rdd après avoir demandé foreach, elle échouera et générera une erreur indiquant
Fichier "<stdin>", ligne 5, dans <module>
AttributeError: l'objet 'NoneType' n'a pas d'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())