Est-il une différence entre foreach et de la carte?
Ok C'est plus une question informatique qu'une question basée sur un langage particulier, mais y a-t-il une différence entre une opération map et une opération foreach? Ou sont-ils simplement des noms différents pour la même chose?
8 réponses
Différent.
Foreach itère sur une liste et applique une opération avec des effets secondaires à chaque membre de la liste (comme l'enregistrement de chacun dans la base de données par exemple)
Map itère sur une liste, transforme chaque membre de cette liste et renvoie une autre liste de la même taille avec les membres transformés (comme 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.
Bref, foreach
est pour appliquer une opération sur chaque élément d'une collection d'éléments, alors que map
est la transformation d'une collection à une autre.
Il existe deux différences significatives entre foreach
et map
.
-
foreach
n'a pas de restrictions conceptuelles sur l'opération qu'il applique, sauf peut-être accepter un élément comme argument. Qui est, l'opération peut ne rien faire, peut avoir un effet secondaire peut retourner une valeur ou ne peut pas retourner une valeur. Tousforeach
se soucie est d'itérer sur une collection d'éléments, et d'appliquer l'opération sur chaque élément.map
, d'un autre côté, a une restriction sur l'opération: il s'attend à ce que l'opération retourne un élément, et accepte probablement aussi un élément comme argument. L'opérationmap
itère sur une collection d'éléments, applique l'opération sur chaque élément et stocke finalement le résultat de chaque appel de l'opération dans une autre collection. En d'autres termes, lemap
transforme {[46] } une collection en une autre. -
foreach
fonctionne avec une seule collection d'éléments. C'est la collection d'entrées.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 voir les deux hiérarchiquement, où map
est une spécialisation de foreach
. C'est-à-dire que vous pouvez utiliser foreach
et que l'opération transforme son argument et insérez-le dans une autre collection. Ainsi, l'algorithme foreach
est une abstraction, une généralisation, de l'algorithme map
. En fait, parce que foreach
n'a aucune restriction sur son fonctionnement, nous pouvons dire en toute sécurité que foreach
est le mécanisme de boucle le plus simple, et 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'expressivité: 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 étendre cette discussion plus loin, et considérer 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, étant donné un élément, insérera ce même élément dans une autre collection. Si vous utilisez foreach
avec cette opération, vous avez effectivement effectué l'algorithme copy
, mais avec une clarté, une expressivité ou une explicitation réduites. Prenons encore plus loin: nous pouvons dire que map
est une spécialisation de copy
, elle-même une spécialisation de foreach
. map
peutchanger l'un des éléments sur lesquels il itère. Si map
ne change aucun des éléments, alors il suffit de copier les éléments, et en utilisant copy {[46] } exprimerait l'intention plus clairement.
L'algorithme foreach
lui-même peut ou non avoir une valeur de retour, selon la langue. En C++, par exemple, foreach
renvoie l'opération qu'il a reçue à l'origine. L'idée est que l' l'opération peut avoir un état, et vous voudrez peut-être que cette opération inspecte comment elle a évolué sur les éléments. map
, aussi, peut ou ne peut pas renvoyer une valeur. En C++ transform
(l'équivalent de map
ici) arrive à renvoyer un itérateur à la fin du conteneur de sortie (collection). Dans 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 ou non être ce qu'ils retournent.
Array.protototype.map
method & Array.protototype.forEach
sont tous deux assez 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 exactement le même résultat.
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
Mais la torsion vient quand vous exécutez le code suivant: -
ici, j'ai simplement assigné le résultat de la valeur de retour à partir des méthodes map et 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 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
Conclusion
Array.prototype.map
renvoie un tableau mais Array.prototype.forEach
ne le fait pas.vous pouvez donc manipuler le tableau retourné à l'intérieur de la fonction de rappel transmise à la méthode map, puis le renvoyer.
Array.prototype.forEach
marche seulement à travers le tableau donné afin que vous puissiez faire vos affaires tout en marchant dans le tableau.
La différence la plus "visible" est que map accumule le résultat dans une nouvelle collection, alors que foreach est fait uniquement pour 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'a pas vraiment d'importance. en fait, certains environnements d'exécution génèrent du code parallèle, ou même introduisent une mémorisation pour éviter d'appeler des valeurs répétées, ou la lazyness, pour éviter d'appeler certains à tout.
Foreach, d'autre part, est appelée spécifiquement pour les effets secondaires; par conséquent, l'ordre est important, et ne peuvent généralement pas être parallélisé.
Réponse Courte: map
et forEach
sont différents. En outre, de manière informelle, map
est un surensemble strict de forEach
.
Réponse longue: Tout d'abord, trouvons une description en une ligne de forEach
et map
:
-
forEach
itère sur tous les éléments, en appelant la fonction fournie sur chacun. -
map
itère sur tous les éléments, appelant la fonction fournie sur chacun, et produit un tableau transformé en se souvenant du résultat de chaque fonction appeler.
Dans de nombreuses langues, forEach
est souvent appelé 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.
En utilisant forEach
:
Tâche 1: écrivez une fonction printSquares
, qui accepte un tableau de nombres arr
, et imprime le carré de chaque élément.
Solution 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
En utilisant map
:
Tâche 2: Écrire une fonction selfDot
, qui accepte un tableau de nombres arr
, et retourne un tableau dans lequel chaque élément est le carré de l'élément correspondant dans arr
.
Mis à part: ici, en termes d'argot, nous essayons de quadriller le tableau d'entrée. Formellement mis, Nous essayons de calculer son produit dot avec lui-même.
Solution 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
Comment est map
un surensemble de forEach
?
Vous pouvez utiliser map
, afin de résoudre des tâches, Tâche 1 et Tâche 2 . Cependant, vous ne pouvez pas utiliser forEach
pour résoudre le 2.
Dans Solution 1, si vous remplacez simplement forEach
par map
, la solution sera toujours valide. Dans Solution 2 cependant, le remplacement de map
par {[6] } va casser votre solution de travail précédente.
Implémentant forEach
en termes de map
:
Une autre façon de réaliser la supériorité de map
est de mettre en œuvre forEach
en termes de map
. Comme nous sommes de bons programmeurs, nous ne nous laisserons pas aller dans l'espace de noms de la pollution. Nous appellerons notre forEach
, juste each
.
Array.prototype.each = function (func) {
this.map(func);
};
Maintenant, si vous n'aimez pas le non-sens prototype
, voilà:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
Alors, hum.. Pourquoi est-ce que forEach
existe 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 dump? Bien sûr que non! Si vous ne voulez pas d'une transformation, vous ne devriez pas faire une transformation.
Alors que la carte peut être utilisée pour résoudre Tâche 1 , Il ne devrait probablement pas. pour chacun est le bon candidat pour cela.
Réponse originale:
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
est idéalement définir de telle sorte que a[i] === i
pour i < a.length
. Même ainsi, il démontre la puissance de map()
.
Voici la description officielle de map()
. Notez que map()
peut même changer le tableau sur lequel il est appelé! Grêle map()
.
J'espère que cela a aidé.
Édité 10-Nov-2015: élaboration ajoutée.
Voici un exemple dans Scala utilisant des listes: map renvoie la 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 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 tandis 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 en tant que nouvelle liste, sans affecter la liste d'origine.
Utiliser forEach
lorsque vous souhaitez do quelque chose sur la base de chaque élément de la liste. Vous pourriez ajouter des choses à la page, par exemple. Essentiellement, il est idéal pour quand vous voulez "effets secondaires".
Autres différences: forEach
ne renvoie rien (puisque c'est vraiment une fonction de flux de contrôle), et la fonction transmise obtient des références à l'index et à la liste entière, alors que map renvoie la nouvelle liste et ne passe que dans l'élément courant.