how entre diferencia foreach language-agnostic computer-science map-function

how - ¿Hay alguna diferencia entre foreach y map?



kotlin foreach vs map (8)

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


Array.protototype.map método Array.protototype.map y Array.protototype.forEach son 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)); });

Ellos 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 ejecutas el siguiente código:

Aquí simplemente asigné el resultado del valor de retorno 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 complicado!

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 una matriz, pero Array.prototype.forEach no lo hace. Por lo tanto, puede manipular la matriz devuelta dentro de la función de devolución de llamada pasada al método de mapa y luego devolverla.

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


Aquí hay un ejemplo en Scala usando listas: mapea la lista de devoluciones, foreach no devuelve nada.

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

Entonces, el mapa devuelve la lista resultante de aplicar la función f a cada elemento de 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


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)

el mapa 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)


En resumen, foreach es para aplicar una operación en 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, aparte de quizás aceptar un elemento como argumento. Es decir, la operación no puede hacer nada, puede tener un efecto secundario, puede devolver un valor o puede no devolver un valor. Todo lo que a foreach le importa es 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 de 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 trabaja con una sola colección de elementos. Esta es la colección de entrada.

    map funciona con dos colecciones de elementos: la colección de entrada y la colección de salida.

No es un error relacionar los dos algoritmos: de hecho, puede ver los dos jerárquicamente, donde el map es una especialización de foreach . Es decir, podría usar foreach y hacer que la operación transforme su argumento e insértelo en otra colección. Entonces, el algoritmo foreach es una abstracción, una generalización, del algoritmo de map . De hecho, como foreach no tiene restricciones 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án ahí para expresividad: si desea mapear (o transformar) una colección en otra, su intención es más clara si usa map que si usa foreach .

Podemos ampliar esta discusión y considerar el algoritmo de 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 de copy , aunque con claridad reducida, expresividad o explicación. Vayamos aún más lejos: podemos decir que el map es una especialización de la copy , en sí misma una especialización de foreach . map puede cambiar cualquiera de los elementos sobre los que itera. Si el map no cambia ninguno de los elementos, simplemente copiará los elementos y el uso de la copia expresará la intención más claramente.

El propio algoritmo foreach puede o no tener un valor de retorno, dependiendo del idioma. En C ++, por ejemplo, foreach devuelve la operación que recibió originalmente. La idea es que la operación podría 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 puede devolver un valor. En la transform C ++ (el equivalente para el map aquí) sucede que un iterador regresa al final del contenedor de salida (colección). En Ruby, el valor de retorno del 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.


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


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

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

Use forEach cuando quiera hacer algo en base a cada elemento de la lista. Podría estar agregando cosas a la página, por ejemplo. Esencialmente, es genial para cuando quieres "efectos secundarios".

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


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

pero hay un par de suposiciones adicionales: dado que el ''propósito'' del mapa 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 pereza, para evitar llamar a algunos.

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


Respuesta corta: map y forEach son diferentes. Además, de manera informal, el map es un superconjunto estricto de forEach .

Respuesta larga: primero, presentemos una descripción de las forEach de forEach y del map :

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

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

Ahora, vamos a usar cada una de estas funciones.

Utilizando forEach :

Tarea 1: escriba una función printSquares , que acepte una matriz de números arr , e imprima el cuadrado de cada elemento en ella.

Solución 1:

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

Usando el map :

Tarea 2: escriba 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, estamos tratando de calcular su producto de puntos consigo mismo.

Solución 2:

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

¿Cómo es el map un superconjunto de forEach ?

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

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

Implementando forEach en términos de map :

Otra forma de darse cuenta de la superioridad del map es implementar forEach en términos de map . Como somos buenos programadores, no nos dedicaremos a la contaminación del espacio de nombres. Llamaremos a nuestro forEach , solo a each .

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

Ahora, si no te gusta el prototype sin sentido, aquí tienes:

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

Entonces, umm ... ¿Por forEach incluso existe forEach ?

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

Entonces, mientras que el mapa puede usarse para resolver la Tarea 1 , probablemente no debería. Para cada uno es el candidato adecuado para eso.

Respuesta original:

Si bien estoy totalmente de acuerdo con la respuesta de @madlep, me gustaría señalar que map() es un superconjunto estricto de forEach() .

Sí, map() se usa generalmente para crear una nueva matriz. Sin embargo, también se puede utilizar para cambiar la matriz 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, a se configuró convenientemente de modo que a[i] === i for i < a.length . Aun así, demuestra el poder del map() .

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

Espero que esto haya ayudado.

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