map, filter e reduce
map: transformar cada item
const precosEmCentavos = [1250, 2500, 800];
const emReais = precosEmCentavos.map((centavos) => centavos / 100);
console.log(emReais); // → [12.5, 25, 8]
console.log(precosEmCentavos); // → [1250, 2500, 800] ← intacto
Mesmo tamanho, cada item transformado.
Com objetos:
const produtos = [
{ nome: "Farinha", precoEmCentavos: 1250 },
{ nome: "Açaí", precoEmCentavos: 2500 },
];
const nomes = produtos.map((p) => p.nome);
console.log(nomes); // → ["Farinha", "Açaí"]
const etiquetas = produtos.map((p) => `${p.nome}: R$ ${(p.precoEmCentavos / 100).toFixed(2)}`);
console.log(etiquetas); // → ["Farinha: R$ 12.50", "Açaí: R$ 25.00"]
filter: escolher
const precos = [1250, 2500, 800, 3000];
const baratos = precos.filter((preco) => preco < 2000);
console.log(baratos); // → [1250, 800]
Menos itens (ou nenhum), nunca mais. A função passada devolve true para
manter e false para descartar.
const alunos = [
{ nome: "Ana", idade: 15, matriculado: true },
{ nome: "João", idade: 20, matriculado: false },
{ nome: "Maria", idade: 17, matriculado: true },
];
const matriculados = alunos.filter((a) => a.matriculado);
const menores = alunos.filter((a) => a.idade < 18);
const ambos = alunos.filter((a) => a.matriculado && a.idade < 18);
reduce: juntar tudo num valor
const precos = [1250, 2500, 800];
const total = precos.reduce((soma, preco) => soma + preco, 0);
console.log(total); // → 4550
Dois argumentos:
- a função, que recebe o acumulado até agora e o item atual;
- o valor inicial: aqui,
0.
Passo a passo:
início: soma = 0
item 1: soma = 0 + 1250 = 1250
item 2: soma = 1250 + 2500 = 3750
item 3: soma = 3750 + 800 = 4550
Com objetos:
const carrinho = [
{ produto: "Farinha", quilos: 3, precoPorKgEmCentavos: 1250 },
{ produto: "Açaí", quilos: 2, precoPorKgEmCentavos: 2500 },
];
const total = carrinho.reduce((soma, item) => {
return soma + Math.round(item.precoPorKgEmCentavos * item.quilos);
}, 0);
console.log(`R$ ${(total / 100).toFixed(2)}`); // → R$ 87.50
E reduce não devolve só número. Agrupar, por exemplo:
const alunos = [
{ nome: "Ana", turno: "manha" },
{ nome: "João", turno: "tarde" },
{ nome: "Maria", turno: "manha" },
];
const porTurno = alunos.reduce((grupos, aluno) => {
const atual = grupos[aluno.turno] ?? [];
return { ...grupos, [aluno.turno]: [...atual, aluno.nome] };
}, {});
console.log(porTurno);
// → { manha: ["Ana", "Maria"], tarde: ["João"] }
Encadear
O resultado de um é a entrada do seguinte:
const produtos = [
{ nome: "Farinha", precoEmCentavos: 1250, disponivel: true },
{ nome: "Açaí", precoEmCentavos: 2500, disponivel: true },
{ nome: "Tucumã", precoEmCentavos: 800, disponivel: false },
{ nome: "Cupuaçu", precoEmCentavos: 1800, disponivel: true },
];
const totalDisponivel = produtos
.filter((p) => p.disponivel)
.map((p) => p.precoEmCentavos)
.reduce((soma, preco) => soma + preco, 0);
console.log(`R$ ${(totalDisponivel / 100).toFixed(2)}`); // → R$ 55.50
Lê-se de cima para baixo: filtre os disponíveis, pegue os preços, some.
Compare com o for equivalente:
let total = 0;
for (const p of produtos) {
if (p.disponivel) {
total += p.precoEmCentavos;
}
}
O for não é errado. A diferença é que na versão encadeada o nome do método
já conta a intenção: você lê filter e sabe que ali se escolhe, sem precisar
ler o corpo.
Os primos
const numeros = [1, 2, 3, 4, 5];
numeros.forEach((n) => console.log(n)); // percorre, não devolve nada
numeros.find((n) => n > 3); // → 4, o primeiro
numeros.findIndex((n) => n > 3); // → 3, a posição
numeros.some((n) => n > 4); // → true, algum
numeros.every((n) => n > 0); // → true, todos
numeros.flat(); // achata listas aninhadas
forEach é o for em forma de método: percorre e não devolve nada. Se você
está usando forEach para montar outra lista, o que você quer é map.
A lista da feira, do começo ao fim
const FEIRA = [
{ produto: "Farinha d'água", categoria: "farinha", precoEmCentavos: 1250, estoqueEmKg: 40 },
{ produto: "Farinha seca", categoria: "farinha", precoEmCentavos: 1100, estoqueEmKg: 0 },
{ produto: "Açaí", categoria: "fruta", precoEmCentavos: 2500, estoqueEmKg: 15 },
{ produto: "Tucumã", categoria: "fruta", precoEmCentavos: 800, estoqueEmKg: 22 },
{ produto: "Cupuaçu", categoria: "fruta", precoEmCentavos: 1800, estoqueEmKg: 8 },
];
const emEstoque = FEIRA.filter((item) => item.estoqueEmKg > 0);
console.log(`${emEstoque.length} de ${FEIRA.length} produtos disponíveis`);
const frutas = emEstoque
.filter((item) => item.categoria === "fruta")
.map((item) => `${item.produto} - R$ ${(item.precoEmCentavos / 100).toFixed(2)}/kg`);
console.log(frutas.join("\n"));
const valorDoEstoque = emEstoque.reduce(
(soma, item) => soma + item.precoEmCentavos * item.estoqueEmKg,
0
);
console.log(`Valor total: R$ ${(valorDoEstoque / 100).toFixed(2)}`);
const maisCaro = emEstoque.reduce((maior, item) =>
item.precoEmCentavos > maior.precoEmCentavos ? item : maior
);
console.log(`Mais caro: ${maisCaro.produto}`);
Exercícios
- Com
map, transforme uma lista de preços em centavos numa de reais. - Com
filter, pegue só os alunos maiores de idade. - Com
reduce, some o total de uma compra. - Encadeie os três: filtre os disponíveis, pegue os preços e some.
- Com
reduce, agrupe alunos por turno. - Com
reduce, encontre o produto mais caro. - Reescreva um
forque você tenha escrito antes usandofilterereduce.
Referências
map- MDNfilter- MDNreduce- MDN - com muitos exemplos além da soma
Testa o que você leu
5 perguntas sobre esta aula. Errar aqui não custa nada - a explicação vem junto da correção.