Existe uma diferença entre foreach e mapa?
-
21-08-2019 - |
Pergunta
Ok esta é mais uma questão de ciência da computação, do que uma pergunta com base em uma linguagem particular, mas há uma diferença entre uma operação de mapa e uma operação de foreach? Ou são simplesmente nomes diferentes para a mesma coisa?
Solução
diferente.
itera foreach mais de uma lista e aplica-se alguma operação com efeitos colaterais para cada membro da lista (tais como poupança de cada um para o banco de dados, por exemplo)
mapa itera sobre uma lista, transforma cada membro da referida lista, e volta outra lista do mesmo tamanho com os membros transformadas (tais como a conversão de uma lista de strings em maiúsculas)
Outras dicas
A diferença importante entre eles é que map
acumula todos os resultados em uma coleção, enquanto foreach
retorna nada. map
geralmente é usado quando você quer transformar uma coleção de elementos com uma função, enquanto foreach
simplesmente executa uma ação para cada elemento.
Em suma, foreach
é para aplicar uma operação em cada elemento de um conjunto de elementos, enquanto map
é para transformar uma coleção para outra.
Existem duas diferenças significativas entre foreach
e map
.
-
foreach
não tem restrições conceituais sobre a operação se aplica, à excepção 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 não pode retornar um valor. Todos os cuidadosforeach
cerca é para iterar sobre uma coleção de elementos, e aplicar a operação em cada elemento.map
, por outro lado, tem uma restrição sobre a operação: ele espera que a operação para retornar um elemento, e provavelmente também aceitar um elemento como argumento. A operaçãomap
itera sobre um conjunto de elementos, a aplicação da operação em cada elemento, e, finalmente, armazenando o resultado de cada invocação da operação para uma outra recolha. Em outras palavras, omap
transforma uma coleção para outra. -
foreach
trabalha com um único conjunto de elementos. Esta é a coleção de entrada.map
trabalha com duas coleções de elementos:. A coleção de entrada ea coleta de saída
Não é um erro relacionar os dois algoritmos: na verdade, você pode ver os dois hierarquicamente, onde map
é uma especialização de foreach
. Ou seja, você poderia usar foreach
e ter a operação de transformar seu argumento e inseri-lo em uma outra coleção. Assim, o algoritmo foreach
é uma abstração, uma generalização, do algoritmo map
. Na verdade, porque foreach
não tem nenhuma restrição sobre o seu funcionamento, podemos dizer com segurança que foreach
é o mais simples mecanismo de loop lá fora, e ele pode fazer qualquer coisa um loop pode fazer. map
, bem como outros algoritmos mais especializado, está lá para expressividade: se você deseja mapear (ou transformar) uma coleção para outra, sua intenção é clara, se você usar map
do que se você usar foreach
Podemos estender essa discussão adiante, e considerar o algoritmo copy
: um laço que clona uma coleção. Este algoritmo também é uma especialização do algoritmo foreach
. Pode-se definir uma operação que, tendo em conta um elemento, que irá inserir mesmo elemento para uma outra recolha. Se você usar foreach
com essa operação que com efeito executou o algoritmo copy
, embora com reduzida clareza, expressividade ou explicitação. Vamos levá-lo ainda mais longe: Podemos dizer que map
é uma especialização de copy
,-se uma especialização de foreach
. map
podem mudança qualquer um dos elementos que itera sobre. Se map
não muda qualquer um dos elementos, em seguida, ele apenas Copiado os elementos, e usando cópia expressaria a intenção mais clara.
O algoritmo foreach
em si pode ou não pode ter um valor de retorno, dependendo do idioma. Em C ++, por exemplo, foreach
retorna a operação que originalmente recebido. A ideia é que a operação pode ter um estado, e você pode querer que volta de operações para verificar como ele evoluiu ao longo dos elementos. map
, também, pode ou não retornar um valor. Em C ++ transform
(o equivalente para map
aqui) acontece para retornar uma iteração para a extremidade do recipiente de saída (recolha). Em Ruby, o valor de retorno da map
é a sequência de saída (recolha). Assim, o valor de retorno dos algoritmos é realmente um detalhe de implementação; seu efeito pode ou não ser o que eles retornam.
Array.protototype.map
método & Array.protototype.forEach
ambas bastante similar.
Executar 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 resultado ditto exato.
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
Mas a reviravolta vem quando você executar o seguinte código: -
Aqui eu simplesmente atribuído o resultado do valor de retorno a partir do mapa e forEach métodos.
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
Conclusão
Array.prototype.map
retorna uma matriz, mas Array.prototype.forEach
não. Então você pode manipular a matriz retornada dentro da função callback passado para o método mapa e, em seguida, devolvê-lo.
Array.prototype.forEach
única anda através da matriz dada para que você possa fazer suas coisas enquanto caminhava a matriz.
A diferença mais 'visível' é que o mapa acumula o resultado em uma nova coleção, enquanto foreach é feito apenas para a própria execução.
mas há um par de pressupostos extras: uma vez que o 'propósito' de mapa é a nova lista de valores, isso realmente não importa a ordem de execução. De fato, alguns ambientes de execução gerar código paralelo, ou mesmo introduzir algum memoizing para evitar chamar para valores repetidos, ou preguiça, para evitar chamar alguns em tudo.
foreach, por outro lado, é chamado especificamente para os efeitos secundários; portanto, a ordem é importante, e geralmente não podem ser paralelizado.
Resposta curta: map
e forEach
são diferentes. Além disso, informalmente falando, map
é um super rigoroso de forEach
.
Resposta longa: Primeiro, vamos chegar a um descrições de linha de forEach
e map
:
- itera
forEach
mais de todos os elementos, chamando a função fornecida em cada um. - itera
map
mais de todos os elementos, chamando a função fornecida em cada um, e produz uma matriz transformado por lembrar o resultado de cada chamada de função.
Em muitas línguas, forEach
é muitas vezes chamado apenas each
. A discussão a seguir usa JavaScript apenas para referência. Ele poderia realmente ser qualquer outra língua.
Agora, vamos usar cada uma dessas funções.
Usando forEach
:
printSquares
função, que aceita uma matriz de números arr
, e imprime o quadrado de cada um dos elementos em que
Solução 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
Usando map
:
selfDot
função, que aceita uma matriz de números arr
, e retorna uma matriz em que cada elemento é o quadrado do elemento correspondente em arr
Além: Aqui, em termos de gíria, estamos tentando fazer a quadratura do array de entrada. Formalmente colocar, estamos a tentar calculá-lo de produto escalar com ele mesmo.
Solução 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
Como é map
um super conjunto de forEach
?
Você pode usar map
para resolver as duas tarefas, Tarefa 1 e Tarefa 2 . No entanto, você não pode usar forEach
para resolver o Tarefa 2 .
Em Solução 1 , se você simplesmente substituir forEach
por map
, a solução ainda será válido. Em Solução 2 no entanto, substituindo map
por forEach
vai quebrar a sua solução previamente funcionando.
Implementar forEach
em termos de map
:
Outra forma de perceber a superioridade do map
é implementar forEach
em termos de map
. Como somos bons programadores, vamos não vai entrar em poluição namespace. Vamos chamar nosso forEach
, apenas each
.
Array.prototype.each = function (func) {
this.map(func);
};
Agora, se você não gosta do absurdo prototype
, aqui vai:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
Então, umm .. Por do que forEach
ainda existe?
A resposta é eficiência. Se você não está interessado em transformar um array para outro array, por que você deve calcular a matriz transformada? Só para despejá-lo? Claro que não! Se você não quer uma transformação, você não deve fazer uma transformação.
Assim, enquanto mapa pode ser usado para resolver Tarefa 1 , ele provavelmente não deveria. Para cada um é o candidato certo para isso.
resposta Original:
Enquanto eu concordam amplamente com @madlep 's resposta, eu gostaria de salientar que map()
é um estrita super-set de forEach()
.
Sim, map()
é geralmente usado para criar uma nova matriz. No entanto, pode também 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 fixado de tal modo que a[i] === i
para i < a.length
. Mesmo assim, ele demonstra o poder da map()
.
Aqui está a descrição oficial de map()
. Note-se que map()
pode até mudar a matriz em que é chamado! Hail map()
.
Espero que isso ajudou.
Editado 10-Nov-2015:. Elaboração Adicionado
Aqui está um exemplo em Scala usando listas: mapa lista de retornos, foreach não retorna nada.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Assim mapear retorna a lista resultante da aplicação da função f para 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)
Foreach apenas se 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 de Javascript em particular, a diferença é que map
é uma função loop while forEach
é um iterador.
Use map
quando você deseja aplicar uma operação para cada membro da lista e obter os resultados de volta como uma nova lista, sem afetar a lista original.
Use forEach
quando você quiser do algo na base de cada elemento da lista. Você pode estar adicionando coisas para a página, por exemplo. Essencialmente, é ótimo para quando você quiser "efeitos colaterais".
Outras diferenças: forEach
retorna nada (uma vez que é realmente uma função de controle de fluxo), eo passou-in função obtém referências para o índice e toda a lista, enquanto mapa regressa a nova lista e só passa no elemento atual.
ForEach tenta aplicar uma função, como escrevendo para db etc em cada elemento do RDD sem retornar nada de volta.
Mas o map()
aplica alguma função sobre os elementos da RDD e retorna o RDD. Então, quando você executar o abaixo método não irá falhar em line3 mas ao coletar o RDD após a aplicação foreach ele vai falhar e lançar um erro que diz
File "
", linha 5, em AttributeError: objeto 'NoneType' tem nenhum atributo 'cobrar'
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())