¿Hay alguna diferencia entre foreach y map?


Ok esta es más una pregunta de ciencias de la computación, que una pregunta basada en un lenguaje en particular, pero ¿hay una diferencia entre una operación de mapa y una operación foreach? O son, simplemente, diferentes nombres para la misma cosa?

Author: hippietrail, 2008-12-10

8 answers

Diferente.

Foreach itera sobre una lista y aplica alguna operación con efectos secundarios a cada miembro de la lista (como guardar cada uno en la base de datos, por ejemplo)

Map itera sobre una lista, transforma cada miembro de esa lista y devuelve otra lista del mismo tamaño con los miembros transformados (como convertir una lista de cadenas a mayúsculas)

 277
Author: madlep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-10 02:14:53

La diferencia importante entre ellos es que map acumula todos los resultados en una colección, mientras que foreach no devuelve nada. map se usa normalmente cuando se quiere transformar una colección de elementos con una función, mientras que foreach simplemente ejecuta una acción para cada elemento.

 111
Author: Henk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-10 02:15:31

En resumen, foreach es para aplicar una operación a cada elemento de una colección de elementos, mientras que map es para transformar una colección en otra.

Hay dos diferencias significativas entre foreach y map.

  1. foreach no tiene restricciones conceptuales sobre la operación que aplica, excepto tal vez aceptar un elemento como argumento. Es decir, la operación puede no hacer nada, puede tener un efecto secundario, puede devolver un valor o no puede devolver un valor. Todos foreach se preocupa por iterar sobre una colección de elementos, y aplicar la operación en cada elemento.

    map, por otro lado, tiene una restricción en la operación: espera que la operación devuelva un elemento, y probablemente también acepte un elemento como argumento. La operación map itera sobre una colección de elementos, aplicando la operación en cada elemento, y finalmente almacenando el resultado de cada invocación de la operación en otra colección. En otras palabras, el map transforma una colección en otra.

  2. foreach funciona con una sola colección de elementos. Esta es la colección de entrada.

    map funciona con dos colecciones de elementos: la colección input y la colección output.

No es un error relacionar los dos algoritmos: de hecho, puede ver los dos jerárquicamente, donde map es una especialización de foreach. Es decir, podría usar foreach y hacer que la operación transforme su argumento e insertarlo en otra colección. Por lo tanto, el algoritmo foreach es una abstracción, una generalización, del algoritmo map. De hecho, debido a que foreach no tiene ninguna restricción en su funcionamiento, podemos decir con seguridad que foreach es el mecanismo de bucle más simple que existe, y puede hacer cualquier cosa que un bucle pueda hacer. map, así como otros algoritmos más especializados, está ahí para la expresividad: si desea mapear (o transformar) una colección en otra, su intención es más clara si utiliza map que si usa foreach.

Podemos extender esta discusión aún más, y considerar el algoritmo copy: un bucle que clona una colección. Este algoritmo también es una especialización del algoritmo foreach. Podría definir una operación que, dado un elemento, insertará ese mismo elemento en otra colección. Si usa foreach con esa operación, en efecto realizó el algoritmo copy, aunque con claridad, expresividad o explicitud reducidas. Vayamos aún más lejos: Podemos decir que map es una especialización de copy, en sí misma una especialización de foreach. mapmay change any of the elements iterates over. Si map no cambia ninguno de los elementos, entonces simplemente copió los elementos, y usando copiar expresaría la intención más claramente.

El algoritmo foreach puede o no tener un valor de retorno, dependiendo del lenguaje. En C++, por ejemplo, foreach devuelve la operación que recibió originalmente. La idea es que el la operación puede tener un estado, y es posible que desee que la operación vuelva a inspeccionar cómo evolucionó sobre los elementos. map, también, puede o no devolver un valor. En C++ transform (el equivalente para map aquí) sucede que devuelve un iterador al final del contenedor de salida (colección). En Ruby, el valor de retorno de map es la secuencia de salida (colección). Por lo tanto, el valor de retorno de los algoritmos es realmente un detalle de implementación; su efecto puede o no ser lo que devuelven.

 40
Author: wilhelmtell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-28 23:53:40

Array.protototype.map método & Array.protototype.forEach son ambos bastante similares.

Ejecute el siguiente código: 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));
});

Dan el mismo resultado exacto.

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

Pero el giro viene cuando se ejecuta el siguiente código: -

Aquí simplemente he asignado el resultado del valor devuelto de los métodos map y 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();

Ahora el resultado es algo ¡tricky!

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

Conclusión

Array.prototype.map devuelve un array pero Array.prototype.forEach no. Así que puede manipular el array devuelto dentro de la función callback pasada al método map y luego devolverlo.

Array.prototype.forEach solo camina a través de la matriz dada para que pueda hacer sus cosas mientras camina por la matriz.

 30
Author: abhisekp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-02 11:19:15

La diferencia más 'visible' es que map acumula el resultado en una nueva colección, mientras que foreach se hace solo para la ejecución en sí.

Pero hay un par de suposiciones adicionales: dado que el 'propósito' de map es la nueva lista de valores, realmente no importa el orden de ejecución. de hecho, algunos entornos de ejecución generan código paralelo, o incluso introducen algunas memorias para evitar llamar a valores repetidos, o holgazanería, para evitar llamar a algunos en todo.

Foreach, por otro lado, se llama específicamente para los efectos secundarios; por lo tanto, el orden es importante, y generalmente no se puede paralelizar.

 11
Author: Javier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-25 15:52:46

Respuesta Corta: map y forEach son diferentes. También, informalmente hablando, map es un superconjunto estricto de forEach.

Respuesta larga: Primero, vamos a llegar a una descripción de una línea de forEach y map:

  • forEach itera sobre todos los elementos, llamando a la función suministrada en cada uno.
  • map itera sobre todos los elementos, llamando a la función suministrada en cada uno, y produce una matriz transformada recordando el resultado de cada función llamada.

En muchos idiomas, forEach a menudo se llama simplemente each. La siguiente discusión utiliza JavaScript solo como referencia. Realmente podría ser cualquier otro idioma.

Ahora, usemos cada una de estas funciones.

Usando forEach:

Tarea 1: Escribe una función printSquares, que acepta una matriz de números arr, e imprime el cuadrado de cada elemento en ella.

Solución 1:

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

Usando map:

Tarea 2: Escribe una función selfDot, que acepta una matriz de números arr, y devuelve una matriz en la que cada elemento es el cuadrado del elemento correspondiente en arr.

Aparte: Aquí, en términos de argot, estamos tratando de cuadrar la matriz de entrada. Formalmente puesto, estamos tratando de calcular su producto punto con sí mismo.

Solución 2:

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

¿Cómo es map un superconjunto de forEach?

Puede usar map para resolver ambas tareas, Tarea 1 y Tarea 2 . Sin embargo, no puede usar forEach para resolver la tarea 2.

En Solución 1, si simplemente reemplaza forEach por map, la solución seguirá siendo válida. En Solución 2 sin embargo, reemplazar map por forEach romperá su solución que funcionaba anteriormente.

Implementing forEach in terms of map:

Otra forma de realizar la superioridad de map es implementar forEach en términos de map. Como somos buenos programadores, no nos complaceremos in namespace pollution. Llamaremos a nuestro forEach, solo each.

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

Ahora, si no te gustan las prototype tonterías, aquí tienes:{[52]]}

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

Así que, umm.. ¿Por qué existe forEach?

La respuesta es la eficiencia. Si no está interesado en transformar una matriz en otra matriz, ¿por qué debería calcular la matriz transformada? ¿Sólo para tirarlo? ¡Claro que no! Si no quieres una transformación, no deberías hacer una transformación.

Así que mientras que el mapa se puede utilizar para resolver Tarea 1, probablemente no debería. Para cada uno es el candidato correcto para eso.


Respuesta original:

Aunque estoy en gran medida de acuerdo con la respuesta de @madlep, me gustaría señalar que map() es un super-conjunto estricto de forEach().

Sí, map() se usa generalmente para crear una nueva matriz. Sin embargo, puede también ser usado para cambiar el array actual.

Aquí hay un ejemplo:

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!!"]

En el ejemplo anterior, {[42] } fue convenientemente establecer de tal manera que a[i] === i para i < a.length. Aun así, demuestra el poder de map().

Aquí está la descripción oficial de map(). Tenga en cuenta que map() puede incluso cambiar la matriz en la que se llama! Hail map().

Espero que esto haya ayudado.


Editado el 10-Nov-2015: Elaboración añadida.

 11
Author: Sumukh Barve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 15:27:03

Aquí hay un ejemplo en Scala usando listas: map returns list, foreach returns nothing.

def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit

So map devuelve la lista resultante de aplicar la función f a cada elemento de la lista:

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 solo aplica f a cada elemento:

scala> var sum = 0
sum: Int = 0

scala> list foreach (sum += _)

scala> sum
res2: Int = 6 // res1 is empty
 3
Author: irudyak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-13 07:56:27

Si estás hablando de Javascript en particular, la diferencia es que map es una función de bucle mientras que forEach es un iterador.

Use map cuando desee aplicar una operación a cada miembro de la lista y obtener los resultados como una nueva lista, sin afectar a la lista original.

Use forEach cuando desee hacer algo sobre la base de cada elemento de la lista. Podrías estar agregando cosas a la página, por ejemplo. Esencialmente, es ideal para cuando quieras "efectos secundarios".

Otras diferencias: forEach no devuelve nada (ya que en realidad es una función de control de flujo), y la función passed-in obtiene referencias al índice y a toda la lista, mientras que map devuelve la nueva lista y solo pasa el elemento actual.

 2
Author: phyzome,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-10 02:19:28