Ok, isso é mais uma questão de ciência da computação do que uma questão baseada em um idioma específico, mas existe uma diferença entre uma operação de mapa e uma operação foreach? Ou eles são simplesmente nomes diferentes para a mesma coisa?
Ok, isso é mais uma questão de ciência da computação do que uma questão baseada em um idioma específico, mas existe uma diferença entre uma operação de mapa e uma operação foreach? Ou eles são simplesmente nomes diferentes para a mesma coisa?
Respostas:
Diferente.
O foreach itera sobre uma lista e aplica alguma operação com efeitos colaterais a cada membro da lista (como salvar cada um no banco de dados, por exemplo)
O mapa itera sobre uma lista, transforma cada membro dessa lista e retorna outra lista do mesmo tamanho com os membros transformados (como converter uma lista de cadeias de caracteres em maiúsculas)
map
que não resultam na execução de sua lógica subjacente até quando a lista transformado esperado é convocado. Por outro lado, foreach
a operação é calculada imediatamente.
A diferença importante entre eles é que map
acumula todos os resultados em uma coleção, enquanto foreach
não retorna nada. map
geralmente é usado quando você deseja transformar uma coleção de elementos com uma função, enquanto foreach
simplesmente executa uma ação para cada elemento.
Em resumo, foreach
é para aplicar uma operação em cada elemento de uma coleção de elementos, ao passo que map
é para transformar uma coleção em outra.
Existem duas diferenças significativas entre foreach
e map
.
foreach
não possui restrições conceituais sobre a operação que aplica, além de talvez aceitar um elemento como argumento. Ou seja, a operação pode não fazer nada, pode ter um efeito colateral, pode retornar um valor ou pode não retornar um valor. O que foreach
importa é iterar sobre uma coleção de elementos e aplicar a operação em cada elemento.
map
, por outro lado, tem uma restrição à operação: espera que a operação retorne um elemento e provavelmente também aceite um elemento como argumento. A map
operação itera sobre uma coleção de elementos, aplicando a operação em cada elemento e, finalmente, armazenando o resultado de cada chamada da operação em outra coleção. Em outras palavras, o map
transforma uma coleção em outra.
foreach
trabalha com uma única coleção de elementos. Esta é a coleção de entrada.
map
trabalha com duas coleções de elementos: a coleção de entrada e a coleção de saída.
Não é um erro relacionar os dois algoritmos: na verdade, você pode visualizar os dois hierarquicamente, de onde map
é uma especialização foreach
. Ou seja, você pode usar foreach
e fazer com que a operação transforme seu argumento e o insira em outra coleção. Portanto, o foreach
algoritmo é uma abstração, uma generalização, do map
algoritmo. De fato, como foreach
não há restrição em sua operação, podemos dizer com segurança que esse foreach
é o mecanismo de loop mais simples existente no mercado e pode fazer qualquer coisa que um loop possa fazer. map
, além de outros algoritmos mais especializados, existe expressividade: se você deseja mapear (ou transformar) uma coleção em outra, sua intenção é mais clara se você usar do map
que se usar foreach
.
Podemos estender mais essa discussão e considerar o copy
algoritmo: um loop que clona uma coleção. Este algoritmo também é uma especialização do foreach
algoritmo. Você pode definir uma operação que, dado um elemento, insira esse mesmo elemento em outra coleção. Se você usar foreach
essa operação, você efetivamente executou o copy
algoritmo, embora com menor clareza, expressividade ou explicitação. Vamos levar ainda mais longe: podemos dizer que map
é uma especialização de copy
, ela própria uma especialização de foreach
. map
pode alterar qualquer um dos elementos que itera. Se map
não altera nenhum dos elementos, apenas copia os elementos e usa copy expressaria a intenção mais claramente.
O foreach
próprio algoritmo pode ou não ter um valor de retorno, dependendo do idioma. Em C ++, por exemplo, foreach
retorna a operação que recebeu originalmente. A idéia é que a operação possa ter um estado, e você pode querer que ela volte a inspecionar como evoluiu sobre os elementos. map
também pode ou não retornar um valor. Em C ++ transform
(o equivalente map
aqui) retorna um iterador para o final do contêiner de saída (coleção). No Ruby, o valor de retorno map
é a sequência de saída (coleção). Portanto, o valor de retorno dos algoritmos é realmente um detalhe de implementação; seu efeito pode ou não ser o que eles retornam.
.forEach()
pode ser usado para implementar .map()
, consulte aqui: stackoverflow.com/a/39159854/1524693 #
Array.protototype.map
método e Array.protototype.forEach
são ambos bastante semelhantes.Execute o seguinte 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));
});
Eles dão o mesmo resultado.
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
Aqui, eu simplesmente atribuí o resultado do valor de retorno dos métodos map e 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();
Agora o resultado é 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
retorna uma matriz, mas Array.prototype.forEach
não. Portanto, você pode manipular a matriz retornada dentro da função de retorno de chamada passada para o método map e depois devolvê-la.
Array.prototype.forEach
apenas percorre a matriz fornecida para que você possa fazer suas coisas enquanto caminha pela matriz.
a diferença mais "visível" é que o mapa acumula o resultado em uma nova coleção, enquanto o foreach é feito apenas para a própria execução.
mas há algumas suposições extras: como o "objetivo" do mapa é a nova lista de valores, isso realmente não importa a ordem de execução. de fato, alguns ambientes de execução geram código paralelo ou até introduzem algumas memoizing para evitar exigir valores repetidos, ou preguiça, para evitar chamar alguns.
o foreach, por outro lado, é chamado especificamente para os efeitos colaterais; portanto, a ordem é importante e geralmente não pode ser paralelizada.
Resposta curta: map
e forEach
são diferentes. Além disso, informalmente, map
é um superconjunto estrito de forEach
.
Resposta longa: Primeiro, vamos apresentar descrições de uma linha forEach
e map
:
forEach
itera sobre todos os elementos, chamando a função fornecida em cada um.map
itera sobre todos os elementos, chamando a função fornecida em cada um e produz uma matriz transformada lembrando o resultado de cada chamada de função.Em muitos idiomas, forEach
costuma ser chamado apenas each
. A discussão a seguir usa JavaScript apenas para referência. Poderia realmente ser qualquer outro idioma.
Agora, vamos usar cada uma dessas funções.
forEach
:Tarefa 1: Escreva uma função printSquares
que aceite uma matriz de números arr
e imprima o quadrado de cada elemento nela.
Solução 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:Tarefa 2: Escreva uma função selfDot
que aceite uma matriz de números arr
e retorne uma matriz em que cada elemento é o quadrado do elemento correspondente emarr
.
Além: Aqui, em termos de gíria, estamos tentando quadrar o array de entrada. Em termos gerais, estamos tentando calcular o produto escalar consigo mesmo.
Solução 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
um superconjunto deforEach
?Você pode usar map
para resolver as duas tarefas, Tarefa 1 e Tarefa 2 . No entanto, você não pode usar forEach
para resolver a tarefa 2 .
Na solução 1 , se você simplesmente substituir forEach
por map
, a solução ainda será válida. Na solução 2 , no entanto, a substituição map
por forEach
interromperá a solução que estava funcionando anteriormente.
forEach
em termos de map
:Outra maneira de perceber map
a superioridade é implementar forEach
em termos de map
. Como somos bons programadores, não vamos entrar em poluição por namespace. Vamos ligar para o nosso forEach
, apenas each
.
Array.prototype.each = function (func) {
this.map(func);
};
Agora, se você não gosta do prototype
absurdo, aqui está:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
existe?A resposta é eficiência. Se você não está interessado em transformar uma matriz em outra matriz, por que calcular a matriz transformada? Apenas para despejar? Claro que não! Se você não quer uma transformação, não deve fazer uma transformação.
Portanto, embora o mapa possa ser usado para resolver a Tarefa 1 , provavelmente não deveria. Pois cada um é o candidato certo para isso.
Embora eu concorde amplamente com a resposta de @madlep, gostaria de salientar que esse map()
é um superconjunto estrito de forEach()
.
Sim, map()
geralmente é usado para criar uma nova matriz. No entanto, também pode ser usado para alterar a matriz atual.
Aqui está um exemplo:
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!!"]
No exemplo acima, a
foi convenientemente definido a[i] === i
para que i < a.length
. Mesmo assim, demonstra o poder de map()
.
Aqui está a descrição oficial demap()
. Observe que map()
pode até alterar a matriz na qual é chamada! Salve map()
.
Espero que isso tenha ajudado.
Editado em 10/11/2015: Elaboração adicionada.
map
função nativa , mas não forEach
; você simplesmente não poderia usar em map
vez de forEach
? Por outro lado, se um idioma tivesse forEach
mas não map
, você teria que implementar o seu próprio map
. Você não poderia simplesmente usar em forEach
vez de map
. Me diga o que você acha.
Aqui está um exemplo no Scala usando listas: mapa retorna lista, foreach não retorna nada.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Portanto, map retorna a lista resultante da aplicação da função f em cada elemento da 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)
O Foreach apenas aplica f a cada elemento:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Se você está falando sobre Javascript em particular, a diferença é que map
é uma função de loop enquanto forEach
é um iterador.
Use map
quando quiser aplicar uma operação a cada membro da lista e obter os resultados novamente como uma nova lista, sem afetar a lista original.
Use forEach
quando quiser fazer algo com base em cada elemento da lista. Você pode adicionar coisas à página, por exemplo. Essencialmente, é ótimo para quando você deseja "efeitos colaterais".
Outras diferenças: forEach
não retorna nada (já que é realmente uma função de fluxo de controle), e a função transmitida obtém referências ao índice e a lista inteira, enquanto o mapa retorna a nova lista e passa apenas no elemento atual.
O ForEach tenta aplicar uma função como escrever em db etc em cada elemento do RDD sem retornar nada.
Mas o map()
aplica alguma função sobre os elementos de rdd e retorna o rdd. Portanto, quando você executa o método abaixo, ele não falha na linha3, mas ao coletar o rdd após aplicar o foreach, ele falha e gera um erro que diz
Arquivo "<stdin>", linha 5, em <module>
AttributeError: o objeto 'NoneType' não tem 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]
dosscala.io.Source.fromFile("/home/me/file").getLines()
e aplicar.foreach(s => ptintln(s))
a ele, ele é impresso ok, mas fica certo vazio depois. Ao mesmo tempo, se eu aplicar.map(ptintln(_))
, ele fica vazio e nada é impresso.