Métodos de array: map, filter, reduce, find, some, every

1. Introdução aos Métodos Funcionais de Array

O JavaScript moderno — especialmente em ambientes Node.js e React — adotou fortemente o paradigma funcional para manipulação de dados. Em vez de escrever loops for explícitos com variáveis mutáveis, utilizamos métodos de array de alta ordem que expressam intenção de forma clara e concisa.

Esses métodos operam sobre arrays sem modificar o array original (imutabilidade), retornando um novo array ou valor. Isso é crucial no React, onde mutações de estado podem causar bugs difíceis de rastrear. Além disso, esses métodos podem ser encadeados, criando pipelines de dados elegantes.

Os seis métodos que veremos — map, filter, reduce, find, some e every — cobrem praticamente todas as operações comuns de transformação, seleção, busca e teste de arrays.

2. map(): Transformando Arrays

O método map() cria um novo array com os resultados da aplicação de uma função a cada elemento do array original. Sua sintaxe é:

const novoArray = arrayOriginal.map((elemento, índice, array) => {
  // retorna o elemento transformado
});

Exemplo prático no React: transformar dados de uma API para renderizar componentes.

// Dados recebidos de uma API
const usuarios = [
  { id: 1, nome: 'Ana', email: 'ana@email.com' },
  { id: 2, nome: 'Carlos', email: 'carlos@email.com' }
];

// Transformar para props de componente React
const usuariosComAvatar = usuarios.map(usuario => ({
  ...usuario,
  avatar: `https://api.adorable.io/avatars/50/${usuario.email}.png`
}));

Cuidado importante: ao retornar objetos em arrow functions, use parênteses para evitar ambiguidade com o corpo da função:

// ❌ Errado: retorna undefined (interpreta chaves como bloco)
const errado = usuarios.map(usuario => { nome: usuario.nome });

// ✅ Correto: retorna o objeto
const correto = usuarios.map(usuario => ({ nome: usuario.nome }));

3. filter(): Selecionando Elementos

filter() retorna um novo array contendo apenas os elementos que satisfazem a condição definida por uma função predicado (que retorna true ou false).

const numerosPares = [1, 2, 3, 4, 5, 6].filter(num => num % 2 === 0);
// [2, 4, 6]

Caso de uso em React: filtrar tarefas em um gerenciador de tarefas.

const tarefas = [
  { id: 1, texto: 'Estudar React', concluida: true },
  { id: 2, texto: 'Fazer exercícios', concluida: false },
  { id: 3, texto: 'Ler documentação', concluida: false }
];

const tarefasPendentes = tarefas.filter(tarefa => !tarefa.concluida);

Combinação com map(): é comum filtrar e depois transformar os dados.

const nomesPendentes = tarefas
  .filter(tarefa => !tarefa.concluida)
  .map(tarefa => tarefa.texto);
// ['Fazer exercícios', 'Ler documentação']

4. reduce(): Acumulando Valores

reduce() é o mais versátil dos métodos. Ele executa uma função redutora para cada elemento, resultando em um único valor acumulado.

array.reduce((acumulador, elementoAtual, índice, array) => {
  // retorna o novo acumulador
}, valorInicial);

Exemplo clássico: somar valores de um array.

const numeros = [10, 20, 30];
const soma = numeros.reduce((acc, num) => acc + num, 0);
// 60

Agrupamento de dados: transformar um array em um objeto agrupado.

const pessoas = [
  { nome: 'Ana', idade: 25 },
  { nome: 'Carlos', idade: 30 },
  { nome: 'Beatriz', idade: 25 }
];

const agrupadoPorIdade = pessoas.reduce((acc, pessoa) => {
  const idade = pessoa.idade;
  if (!acc[idade]) acc[idade] = [];
  acc[idade].push(pessoa);
  return acc;
}, {});
// { '25': [{ nome: 'Ana', ... }, { nome: 'Beatriz', ... }], '30': [...] }

Implementando map com reduce: para entender o poder do método.

function mapComReduce(array, fn) {
  return array.reduce((acc, elemento) => {
    acc.push(fn(elemento));
    return acc;
  }, []);
}

5. find() e findIndex(): Buscando Elementos Únicos

find() retorna o primeiro elemento que satisfaz a condição. Se nenhum for encontrado, retorna undefined.

findIndex() retorna o índice do primeiro elemento que satisfaz a condição, ou -1 se não encontrado.

const numeros = [10, 20, 30, 40];
const primeiroMaiorQue25 = numeros.find(num => num > 25); // 30
const indicePrimeiroMaiorQue25 = numeros.findIndex(num => num > 25); // 2

Uso em React: encontrar um item por ID em uma lista de estado.

const [itens, setItens] = useState([...]);

function encontrarItemPorId(id) {
  const item = itens.find(item => item.id === id);
  return item || null; // fallback para undefined
}

function atualizarItem(id, novosDados) {
  const index = itens.findIndex(item => item.id === id);
  if (index !== -1) {
    const novosItens = [...itens];
    novosItens[index] = { ...novosItens[index], ...novosDados };
    setItens(novosItens);
  }
}

6. some() e every(): Testes de Condição

some() retorna true se pelo menos um elemento satisfaz a condição.

every() retorna true se todos os elementos satisfazem a condição.

const notas = [7, 8, 5, 9, 6];

const alguemReprovou = notas.some(nota => nota < 6); // true (nota 5)
const todosPassaram = notas.every(nota => nota >= 6); // false

Aplicação em validação de formulários no React:

function Formulario() {
  const [campos, setCampos] = useState([
    { nome: 'email', valor: '', valido: false },
    { nome: 'senha', valor: '', valido: false }
  ]);

  const formularioValido = campos.every(campo => campo.valido);

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!formularioValido) {
      alert('Preencha todos os campos corretamente');
      return;
    }
    // enviar dados...
  };
}

7. Combinação e Encadeamento na Prática

Vamos criar um pipeline de dados realista: processar pedidos de uma API no Node.js.

const pedidos = [
  { id: 1, cliente: 'Ana', valor: 150, status: 'entregue' },
  { id: 2, cliente: 'Carlos', valor: 200, status: 'pendente' },
  { id: 3, cliente: 'Beatriz', valor: 50, status: 'entregue' },
  { id: 4, cliente: 'Daniel', valor: 300, status: 'cancelado' },
  { id: 5, cliente: 'Eva', valor: 100, status: 'entregue' }
];

// Pipeline: filtrar entregues → extrair valores → somar
const totalEntregue = pedidos
  .filter(pedido => pedido.status === 'entregue')
  .map(pedido => pedido.valor)
  .reduce((acc, valor) => acc + valor, 0);

console.log(totalEntregue); // 300 (150 + 50 + 100)

Boas práticas de performance:

  • Coloque filter antes de map para reduzir o número de elementos processados.
  • Para arrays muito grandes, considere usar for tradicional se a performance for crítica.
  • Evite encadeamentos excessivos que prejudiquem a legibilidade (mais de 3-4 métodos).
// ❌ Encadeamento excessivo e confuso
const resultado = dados
  .filter(a)
  .map(b)
  .filter(c)
  .reduce(d)
  .filter(e);

// ✅ Quebre em etapas nomeadas
const filtrados = dados.filter(a);
const mapeados = filtrados.map(b);
const resultado = mapeados.reduce(d);

8. Conclusão e Próximos Passos

Dominar esses seis métodos é essencial para escrever código JavaScript moderno, limpo e funcional. Eles são a base para manipulação de dados em Node.js e React.

Método Retorna Quando usar
map Novo array (mesmo tamanho) Transformar cada elemento
filter Novo array (menor ou igual) Selecionar elementos
reduce Valor único Agregar dados
find Elemento ou undefined Buscar primeiro match
some boolean Testar se algum satisfaz
every boolean Testar se todos satisfazem

Armadilhas comuns: não mutar o array original, lembrar que find retorna undefined (não lança erro), e que reduce precisa de valor inicial em arrays vazios para evitar erro.

Esses métodos se conectam naturalmente com outros tópicos da série, como closures (callbacks capturam escopo) e desestruturação (para extrair propriedades dentro dos callbacks).

Referências