W3docs

Entendendo a Função array_udiff() do PHP

Aprenda como array_udiff() do PHP compara arrays com um callback definido pelo usuário e retorna valores presentes apenas no primeiro array.

array_udiff() calcula a diferença entre arrays comparando seus valores com uma função de callback que você fornece. Ela retorna os valores presentes no primeiro array que não são encontrados em nenhum dos outros arrays. O "u" no nome significa user-defined (definido pelo usuário) — ao contrário de array_diff(), que compara valores como strings, array_udiff() permite que você decida exatamente quando dois valores são considerados "iguais".

Esta página cobre a sintaxe da função, como o callback funciona, exemplos executáveis com números e objects, e as armadilhas comuns a observar.

Quando usar array_udiff()?

Use array_udiff() sempre que a comparação padrão de array_diff() for insuficiente:

  • Objects. array_diff() converte cada valor em uma string. Objects sem um método __toString() não podem ser comparados dessa forma, então você precisa de um callback que inspecione uma propriedade.
  • Igualdade personalizada. Você quer uma comparação sem distinção de maiúsculas e minúsculas, uma comparação por um único campo, ou uma comparação numérica baseada em tolerância.
  • Dados mistos ou normalizados. Você quer tratar "5", 5 e 5.0 como o mesmo valor, ou comparar floats com arredondamento.

Se você só precisa de comparação simples de string, prefira o array_diff() mais simples.

Como array_udiff() funciona

A função recebe dois ou mais arrays, sendo o último argumento o callback de comparação. Ela retorna um array dos valores do primeiro array que o callback não encontra iguais a nenhum valor nos arrays seguintes. As chaves e a ordem do primeiro array são preservadas.

Sintaxe

array_udiff(array $array1, array $array2, array ...$arrays, callable $value_compare_func): array
  • array $array1 — o array cujos valores são retornados (o array "base").
  • array $array2 — um array para comparar.
  • array ...$arrays — qualquer número de arrays adicionais para comparar.
  • callable $value_compare_func — o callback de comparação. É sempre o último argumento.

O callback de comparação

O callback recebe dois valores e deve retornar um inteiro:

  • um número menor que 0 se o primeiro valor for "menor",
  • 0 se os dois valores forem considerados iguais,
  • um número maior que 0 se o primeiro valor for "maior".

Retornar 0 é o que marca dois valores como iguais, portanto um valor em $array1 é excluído do resultado sempre que o callback retornar 0 para ele contra algum valor em um array posterior. Os resultados < 0 / > 0 permitem que o PHP ordene os valores internamente para uma comparação eficiente — acertá-los importa, então não retorne apenas 0 ou 1. O operador spaceship (<=>) é a forma correta mais simples de produzir esse valor.

Exemplo 1: comparando dois arrays de números

Este exemplo usa uma função nomeada como callback para encontrar números que estão em $array1 mas não em $array2:

<?php

function compare_numbers($a, $b) {
    if ($a == $b) {
        return 0;
    } elseif ($a < $b) {
        return -1;
    } else {
        return 1;
    }
}

$array1 = [1, 2, 3, 4, 5];
$array2 = [2, 4, 6];

$result = array_udiff($array1, $array2, 'compare_numbers');

print_r($result);

?>

compare_numbers() retorna 0 sempre que dois valores coincidem, portanto os números correspondentes (2 e 4) são removidos. O resultado preserva as chaves originais de $array1:

Array
(
    [0] => 1
    [2] => 3
    [4] => 5
)

O callback inteiro poderia ser substituído por uma linha usando o operador spaceship: fn($a, $b) => $a <=> $b.

Exemplo 2: comparando arrays de objects

Este é o caso que array_diff() não consegue lidar. Aqui comparamos dois arrays de objects Product pelo id, retornando os produtos que não estão na segunda lista:

<?php

class Product {
    public function __construct(public int $id, public string $name) {}
}

$catalog = [
    new Product(1, 'Keyboard'),
    new Product(2, 'Mouse'),
    new Product(3, 'Monitor'),
];

$discontinued = [
    new Product(2, 'Mouse'),
];

$available = array_udiff(
    $catalog,
    $discontinued,
    fn(Product $a, Product $b) => $a->id <=> $b->id
);

foreach ($available as $product) {
    echo $product->id . ': ' . $product->name . PHP_EOL;
}

?>

Isso imprime os produtos cujo id não está presente em $discontinued:

1: Keyboard
3: Monitor

Como o callback compara apenas o id, os valores diferentes de name são irrelevantes — a lógica de comparação é inteiramente sua para definir.

Pontos importantes

  • O callback é sempre o último argumento, independentemente de quantos arrays você passar.
  • array_udiff() compara valores. Para comparar tanto por chaves quanto por valores, use array_udiff_assoc(); para comparar chaves com um callback também, use array_udiff_uassoc().
  • Retorne um resultado adequado de três vias (negativo / 0 / positivo), não apenas 0 ou 1. O PHP depende da ordenação para comparar eficientemente, e um callback descuidado pode produzir resultados incorretos.
  • O resultado preserva as chaves e a ordem de $array1. Chame array_values() se quiser um array re-indexado.
  • Apenas valores do primeiro array podem aparecer na saída — valores exclusivos dos arrays posteriores nunca são retornados.

Funções relacionadas

Prática

Prática
Qual é o propósito da função array_udiff() em PHP?
Qual é o propósito da função array_udiff() em PHP?
Was this page helpful?