Ok, esta es más una pregunta de informática, que una pregunta basada en un idioma en particular, pero ¿hay alguna diferencia entre una operación de mapa y una operación foreach? ¿O son simplemente nombres diferentes para la misma cosa?
Ok, esta es más una pregunta de informática, que una pregunta basada en un idioma en particular, pero ¿hay alguna diferencia entre una operación de mapa y una operación foreach? ¿O son simplemente nombres diferentes para la misma cosa?
Respuestas:
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 a cada miembro de esa lista y devuelve otra lista del mismo tamaño con los miembros transformados (como convertir una lista de cadenas en mayúsculas)
map
no no da lugar a la ejecución de su lógica subyacente, hasta cuando la lista de espera es convocado transformado. Por el contrario, foreach
la operación se calcula de inmediato.
La diferencia importante entre ellos es que map
acumula todos los resultados en una colección, mientras que foreach
no devuelve nada. map
generalmente se usa cuando desea transformar una colección de elementos con una función, mientras que foreach
simplemente ejecuta una acción para cada elemento.
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
.
foreach
no tiene restricciones conceptuales sobre la operación que aplica, aparte de aceptar un elemento como argumento. Es decir, la operación puede no hacer nada, puede tener un efecto secundario, puede devolver un valor o puede no devolver un valor. Lo único que foreach
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 map
operación 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, map
transforma una colección en otra.
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 map
hay una especialización foreach
. Es decir, puede usar foreach
y hacer que la operación transforme su argumento y lo inserte en otra colección. Entonces, el foreach
algoritmo es una abstracción, una generalización, del map
algoritmo. De hecho, debido a que foreach
no tiene restricciones en su funcionamiento, podemos decir con seguridad que foreach
es el mecanismo de bucle más simple que existe y que 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 la usa map
que si la usa foreach
.
Podemos extender más esta discusión y considerar el copy
algoritmo: un ciclo que clona una colección. Este algoritmo también es una especialización del foreach
algoritmo. Podría definir una operación que, dado un elemento, inserte ese mismo elemento en otra colección. Si utiliza foreach
con esa operación, en realidad realizó el copy
algoritmo, aunque con claridad, expresividad o explicidad reducidas. Vamos a ir aún más lejos: podemos decir que map
es una especialización de copy
, en sí misma una especialización de foreach
. map
puede cambiar cualquiera de los elementos sobre los que itera. Si map
no cambia ninguno de los elementos, simplemente copia los elementos y usa la copia expresaría la intención más claramente.
El foreach
algoritmo en sí 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 volver a inspeccionar cómo evolucionó sobre los elementos. map
, también, puede o no devolver un valor. En C ++ transform
(el equivalente 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). Entonces, el valor de retorno de los algoritmos es realmente un detalle de implementación; su efecto puede o no ser lo que devuelven.
.forEach()
se puede usar para implementar .map()
, consulte aquí: stackoverflow.com/a/39159854/1524693
Array.protototype.map
método 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));
});
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
Aquí simplemente he asignado el resultado del valor de retorno del mapa y para cada método.
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
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 recorre el conjunto dado para que pueda hacer sus cosas mientras recorre el conjunto.
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 misma.
pero hay un par de supuestos adicionales: dado que el "propósito" del mapa es la nueva lista de valores, en realidad 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 pedir valores repetidos, o pereza, para evitar llamar a algunos.
foreach, por otro lado, se llama específicamente por los efectos secundarios; por lo tanto, el orden es importante y generalmente no puede ser paralelizado.
Respuesta corta: map
y forEach
son diferentes. Además, hablando informalmente, map
es un estricto superconjunto de forEach
.
Respuesta larga: Primero, elaboremos descripciones de una línea de forEach
y map
:
forEach
itera sobre todos los elementos, llamando a la función proporcionada en cada uno.map
itera sobre todos los elementos, llama a la función proporcionada en cada uno y produce una matriz transformada al recordar el resultado de cada llamada a la función.En muchos idiomas, a forEach
menudo se le llama justo each
. La siguiente discusión usa JavaScript solo como referencia. Realmente podría ser cualquier otro idioma.
Ahora, usemos cada una de estas funciones.
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);
});
};
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. En términos formales, estamos tratando de calcular su producto punto consigo mismo.
Solución 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
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 la Solución 1 , si simplemente reemplaza forEach
por map
, la solución seguirá siendo válida. Sin embargo, en la Solución 2 , reemplazar map
por forEach
romperá su solución que funcionaba anteriormente.
forEach
en términos demap
:Otra forma de darse cuenta map
de la superioridad es implementar forEach
en términos de map
. Como somos buenos programadores, no nos permitiremos contaminar el espacio de nombres. 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:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
existe?La respuesta es la eficiencia. Si no está interesado en transformar una matriz en otra matriz, ¿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, aunque el mapa se puede usar para resolver la Tarea 1 , probablemente no debería. Para cada uno es el candidato adecuado para eso.
Si bien estoy en gran medida de acuerdo con la respuesta de @madlep, me gustaría señalar que map()
es un súper conjunto estricto de forEach()
.
Sí, map()
generalmente se usa para crear una nueva matriz. Sin embargo, también se puede usar 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
para i < a.length
. Aun así, demuestra el poder de map()
.
Aquí está la descripción oficial demap()
. Tenga en cuenta que map()
incluso puede cambiar la matriz en la que se llama. Granizo map()
.
Espero que esto haya ayudado.
Editado el 10 de noviembre de 2015: elaboración adicional.
map
función nativa pero no forEach
; ¿No podrías simplemente no usar en map
lugar de forEach
? Por otro lado, si un idioma tuviera forEach
pero no map
, tendrías que implementar el tuyo map
. No podrías simplemente usar en forEach
lugar de map
. Dime que piensas.
Aquí hay un ejemplo en Scala usando listas: el mapa devuelve la lista, foreach no devuelve nada.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Entonces 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
Si está hablando de Javascript en particular, la diferencia es que map
es una función de bucle mientras que forEach
es un iterador.
Úselo map
cuando desee aplicar una operación a cada miembro de la lista y recuperar los resultados como una nueva lista, sin afectar la lista original.
Úselo forEach
cuando desee hacer algo en función de cada elemento de la lista. Es posible que esté agregando cosas a la página, por ejemplo. Esencialmente, es ideal para cuando quieres "efectos secundarios".
Otras diferencias: forEach
no devuelve nada (ya que es realmente una función de flujo de control), y la función transferida obtiene referencias al índice y a la lista completa, mientras que map devuelve la nueva lista y solo pasa en el elemento actual.
ForEach intenta aplicar una función como escribir en db, etc. en cada elemento del RDD sin devolver nada.
Pero map()
aplica alguna función sobre los elementos de rdd y devuelve el rdd. Entonces, cuando ejecuta el método a continuación, no fallará en la línea 3, pero al recopilar el rdd después de aplicar foreach, fallará y arrojará un error que dice
Archivo "<stdin>", línea 5, en <module>
AttributeError: el objeto 'NoneType' no tiene el atributo '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())
Iterator[String]
descala.io.Source.fromFile("/home/me/file").getLines()
y aplicarlo.foreach(s => ptintln(s))
a ella, se imprime bien, pero va directo vacía después. Al mismo tiempo, si lo solicito.map(ptintln(_))
, simplemente se vacía y no se imprime nada.