Funções de array: array_map, array_filter, array_reduce e outras

1. Introdução às Funções de Array no PHP

As funções de array de alta ordem (higher-order functions) são funções que recebem outras funções como argumento ou retornam funções como resultado. No PHP, funções como array_map, array_filter e array_reduce permitem processar coleções de dados de forma declarativa e elegante, substituindo loops tradicionais como foreach e for.

A principal vantagem dessas funções é a legibilidade: o código fica mais expressivo e focado no "o que" deve ser feito, não no "como". Em vez de gerenciar manualmente índices e acumuladores, você declara a transformação desejada através de callbacks.

O PHP possui um ecossistema rico de funções de array — são mais de 80 funções nativas. Este artigo foca nas mais poderosas para transformação, filtragem e redução de dados.

2. array_map: Transformando Arrays

A função array_map aplica uma função callback a cada elemento de um ou mais arrays, retornando um novo array com os resultados.

Sintaxe básica:

array_map(callable $callback, array $array, array ...$arrays): array

Exemplo 1: Converter strings para maiúsculas

$nomes = ['ana', 'joão', 'maria', 'pedro'];
$nomesMaiusculos = array_map('strtoupper', $nomes);
// Resultado: ['ANA', 'JOÃO', 'MARIA', 'PEDRO']

Exemplo 2: Trabalhando com múltiplos arrays

$nomes = ['Ana', 'João', 'Maria'];
$idades = [25, 32, 28];

$apresentacoes = array_map(
    fn($nome, $idade) => "$nome tem $idade anos",
    $nomes,
    $idades
);
// Resultado: ['Ana tem 25 anos', 'João tem 32 anos', 'Maria tem 28 anos']

Quando múltiplos arrays são fornecidos, o callback recebe um elemento de cada array na mesma posição. Se os arrays tiverem tamanhos diferentes, o resultado terá o comprimento do maior array (os menores são preenchidos com null).

3. array_filter: Filtrando Elementos

array_filter itera sobre um array e retorna apenas os elementos que satisfazem uma condição definida por um callback.

Sintaxe básica:

array_filter(array $array, ?callable $callback = null, int $mode = 0): array

Exemplo 1: Filtrar números pares

$numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$pares = array_filter($numeros, fn($n) => $n % 2 === 0);
// Resultado: [1 => 2, 3 => 4, 5 => 6, 7 => 8, 9 => 10]

Observe que as chaves originais são preservadas. Para reindexar, use array_values().

Exemplo 2: Remover valores vazios ou nulos

$dados = ['PHP', '', null, 'JavaScript', false, 'Python', 0];
$limpos = array_filter($dados);
// Resultado: [0 => 'PHP', 3 => 'JavaScript', 5 => 'Python']

Por padrão, sem callback, array_filter remove valores considerados false no PHP (false, null, '', 0, '0', []).

Exemplo 3: Usando flags especiais

$dados = [
    'nome' => 'Ana',
    'idade' => 25,
    'email' => '',
    'telefone' => null
];

// Filtrar por chave (ARRAY_FILTER_USE_KEY)
$apenasStrings = array_filter(
    $dados,
    fn($chave) => is_string($chave),
    ARRAY_FILTER_USE_KEY
);

// Filtrar por chave e valor (ARRAY_FILTER_USE_BOTH)
$naoVazios = array_filter(
    $dados,
    fn($valor, $chave) => !empty($valor) && $chave !== 'telefone',
    ARRAY_FILTER_USE_BOTH
);

4. array_reduce: Reduzindo Arrays a um Único Valor

array_reduce aplica uma função callback iterativamente a cada elemento do array, acumulando um resultado único.

Sintaxe básica:

array_reduce(array $array, callable $callback, mixed $initial = null): mixed

Exemplo 1: Somar valores

$valores = [10, 20, 30, 40, 50];
$soma = array_reduce($valores, fn($acumulador, $item) => $acumulador + $item, 0);
// Resultado: 150

Exemplo 2: Encontrar o valor máximo

$notas = [7.5, 8.0, 6.5, 9.0, 7.0];
$maxima = array_reduce(
    $notas,
    fn($max, $nota) => $nota > $max ? $nota : $max,
    $notas[0]
);
// Resultado: 9.0

Exemplo 3: Combinar com outras funções

$transacoes = [
    ['tipo' => 'entrada', 'valor' => 1000],
    ['tipo' => 'saida', 'valor' => 200],
    ['tipo' => 'entrada', 'valor' => 500],
    ['tipo' => 'saida', 'valor' => 150],
];

$saldoFinal = array_reduce(
    $transacoes,
    fn($saldo, $transacao) => 
        $transacao['tipo'] === 'entrada' 
            ? $saldo + $transacao['valor'] 
            : $saldo - $transacao['valor'],
    0
);
// Resultado: 1150

5. Outras Funções Essenciais de Array

array_walk e array_walk_recursive: Diferente de array_map, array_walk modifica o array original por referência e permite passar chaves ao callback.

$pessoas = ['Ana' => 25, 'João' => 32, 'Maria' => 28];
array_walk($pessoas, fn(&$idade, $nome) => $idade += 1);
// $pessoas agora é ['Ana' => 26, 'João' => 33, 'Maria' => 29]

array_merge, array_combine e array_chunk:

// array_merge: combina arrays
$array1 = ['a', 'b', 'c'];
$array2 = ['d', 'e'];
$combinado = array_merge($array1, $array2);
// Resultado: ['a', 'b', 'c', 'd', 'e']

// array_combine: usa um array como chaves e outro como valores
$chaves = ['nome', 'idade', 'cidade'];
$valores = ['Ana', 25, 'São Paulo'];
$pessoa = array_combine($chaves, $valores);
// Resultado: ['nome' => 'Ana', 'idade' => 25, 'cidade' => 'São Paulo']

// array_chunk: divide um array em partes
$numeros = range(1, 10);
$grupos = array_chunk($numeros, 3);
// Resultado: [[1,2,3], [4,5,6], [7,8,9], [10]]

Busca e verificação:

$linguagens = ['PHP', 'JavaScript', 'Python', 'Java'];

// in_array: verifica se valor existe
if (in_array('PHP', $linguagens)) {
    echo "PHP está na lista";
}

// array_search: retorna a chave do valor
$posicao = array_search('Python', $linguagens);
// Resultado: 2

// array_key_exists: verifica se chave existe
$dados = ['nome' => 'Ana', 'idade' => 25];
if (array_key_exists('nome', $dados)) {
    echo "Chave 'nome' existe";
}

6. Combinação e Encadeamento de Funções

O verdadeiro poder dessas funções aparece quando as combinamos em pipelines de processamento de dados.

Exemplo prático: Pipeline de transformação de dados

$pedidos = [
    ['produto' => 'Notebook', 'quantidade' => 2, 'preco' => 3500, 'status' => 'entregue'],
    ['produto' => 'Mouse', 'quantidade' => 5, 'preco' => 150, 'status' => 'pendente'],
    ['produto' => 'Teclado', 'quantidade' => 3, 'preco' => 200, 'status' => 'entregue'],
    ['produto' => 'Monitor', 'quantidade' => 1, 'preco' => 1200, 'status' => 'cancelado'],
    ['produto' => 'Webcam', 'quantidade' => 2, 'preco' => 300, 'status' => 'entregue'],
];

// Pipeline: filtrar entregues -> calcular valor total -> somar
$totalEntregues = array_reduce(
    array_map(
        fn($pedido) => $pedido['quantidade'] * $pedido['preco'],
        array_filter(
            $pedidos,
            fn($pedido) => $pedido['status'] === 'entregue'
        )
    ),
    fn($soma, $valor) => $soma + $valor,
    0
);

echo "Total de pedidos entregues: R$ " . number_format($totalEntregues, 2, ',', '.');
// Resultado: Total de pedidos entregues: R$ 7.900,00

Usando closures anônimas e funções nomeadas:

// Função nomeada para reuso
function calcularValorTotal(array $pedido): float {
    return $pedido['quantidade'] * $pedido['preco'];
}

function filtrarPorStatus(string $status): callable {
    return fn($pedido) => $pedido['status'] === $status;
}

$totalPendentes = array_reduce(
    array_map('calcularValorTotal', 
        array_filter($pedidos, filtrarPorStatus('pendente'))
    ),
    fn($soma, $valor) => $soma + $valor,
    0
);

7. Considerações de Desempenho e Boas Práticas

Performance: Para arrays pequenos (até centenas de elementos), a diferença entre funções de array e loops tradicionais é irrelevante. Para grandes volumes (milhares de elementos), loops foreach podem ser ligeiramente mais rápidos, mas a diferença raramente justifica sacrificar a legibilidade.

Legibilidade e manutenibilidade:
- Prefira funções de array quando a lógica de transformação for clara e direta
- Use loops quando precisar de controle fino sobre a iteração (break, continue, múltiplas condições complexas)
- Evite aninhar muitas funções — se a pipeline ficar complexa, extraia para funções nomeadas

Cuidados com efeitos colaterais:
- array_map e array_filter não modificam o array original (imutabilidade)
- array_walk modifica por referência — use com cautela
- Callbacks devem ser funções puras (sem efeitos colaterais) sempre que possível

8. Conclusão e Próximos Passos

Neste artigo, exploramos as principais funções de array de alta ordem do PHP: array_map para transformação, array_filter para filtragem e array_reduce para redução. Também vimos funções auxiliares como array_walk, array_merge e ferramentas de busca.

Para fixar o aprendizado, tente estes exercícios:
1. Crie uma função que receba um array de números e retorne a média dos quadrados dos números pares (use array_filter, array_map e array_reduce)
2. Implemente um pipeline que processe um array de usuários, filtrando maiores de idade, mapeando para nomes completos e reduzindo a uma string CSV
3. Compare o desempenho de array_filter + array_map vs foreach para 100.000 elementos

Dominar essas funções transformará seu código PHP, tornando-o mais expressivo, funcional e fácil de manter.

Referências