Usando array_udiff_uassoc em PHP
Aprenda a usar a função PHP array_udiff_uassoc para calcular a diferença entre dois ou mais arrays com funções de comparação definidas pelo usuário.
array_udiff_uassoc() calcula a diferença entre dois ou mais arrays verificando tanto as chaves quanto os valores — e permite que você decida como ambos são comparados fornecendo dois callbacks próprios. Um elemento do primeiro array é mantido no resultado somente se nenhum outro array contiver um elemento que corresponda a ele tanto na chave quanto no valor, de acordo com seus callbacks.
Esta página explica exatamente como os dois callbacks interagem (a parte que a maioria das referências ignora), percorre um exemplo executável e mostra quando esta função é a ferramenta certa em comparação com suas variantes mais simples.
O que é array_udiff_uassoc?
array_udiff_uassoc() retorna as entradas de $array1 que não estão presentes em nenhum dos outros arrays. Ao contrário de array_diff(), que compara valores apenas com conversão para string, esta variante verifica chaves e valores juntos e delega ambas as comparações a funções fornecidas pelo usuário — é isso que os dois us no nome significam (udiff = comparação de valor pelo usuário, uassoc = comparação de chave pelo usuário).
A assinatura é:
Sintaxe da função PHP array_udiff_uassoc
array_udiff_uassoc(
array $array1,
array $array2,
array ...$arrays, // one or more additional arrays
callable $value_compare_func,
callable $key_compare_func
): arrayOs dois callbacks são sempre os dois últimos argumentos, nesta ordem: comparação de valor primeiro, comparação de chave segundo. Tudo antes deles é um array. O resultado é um novo array com as entradas de $array1 que sobrevivem à comparação, com suas chaves originais preservadas.
Como o matching realmente funciona. Para cada entrada em
$array1, o PHP percorre os outros arrays em busca de uma entrada cuja chave seja "igual" conforme$key_compare_funce cujo valor seja "igual" conforme$value_compare_func. Se tal correspondência existir em qualquer outro array, a entrada é descartada; caso contrário, é mantida. Uma entrada só é removida quando ambas as comparações indicam igualdade.
Entendendo as funções de comparação
Cada callback recebe dois argumentos e deve retornar um inteiro, exatamente como um comparador de ordenação:
- Retorne
0quando os dois itens forem considerados iguais. - Retorne um inteiro positivo quando o primeiro for "maior".
- Retorne um inteiro negativo quando o primeiro for "menor".
O PHP só se importa se o valor de retorno é 0 (igual) ou não, mas um resultado de três vias consistente é necessário porque a função ordena internamente. O operador nave espacial <=> é a maneira mais fácil de escrever um:
$value_compare_func = fn($a, $b) => $a <=> $b; // strict ordering
$key_compare_func = fn($a, $b) => strcasecmp((string) $a, (string) $b); // case-insensitive keysComo você define ambas as comparações, pode fazer coisas que as funções de diff integradas não conseguem — por exemplo, tratar chaves sem distinção de maiúsculas e minúsculas, ou comparar objetos por uma única propriedade.
Exemplo: uso básico
<?php
function compare_values($a, $b) {
if ($a === $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
function compare_keys($a, $b) {
if ($a === $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
$array1 = array('a' => 'apple', 'b' => 'banana', 'c' => 'cherry', 'd' => 'durian');
$array2 = array('a' => 'apple', 'b' => 'game', 'c' => 'cherry');
$array3 = array('a' => 'apple', 'b' => 'door', 'c' => 'cherry', 'g' => 'durian');
$result = array_udiff_uassoc($array1, $array2, $array3, 'compare_values', 'compare_keys');
print_r($result);
?>Aqui compare_values e compare_keys são comparadores simples de três vias. A chamada faz o diff de $array1 contra $array2 e $array3, mantendo apenas as entradas cuja chave e valor não correspondam a nada nos outros arrays. A saída é:
Array
(
[b] => banana
[d] => durian
)Veja por que cada entrada sobrevive ou é descartada:
a => apple— descartada:$array2(e$array3) tem a mesma chaveae o mesmo valorapple.b => banana— mantida: os outros arrays usam a chaveb, mas seus valores sãogame/door, nãobanana. Os valores diferem, então não há correspondência.c => cherry— descartada: correspondida por ambos os outros arrays.d => durian— mantida:$array3contém o valordurian, mas sob a chaveg, nãod. As chaves diferem, então não há correspondência.
Esse último caso é o ponto central da função: mesmo que o valor durian exista em outro lugar, a chave não corresponde, então a entrada permanece. Um diff apenas por valor como array_udiff() a teria removido.
Exemplo: chaves sem distinção de maiúsculas e minúsculas
Como a comparação de chaves é sua para definir, você pode ignorar a capitalização das chaves enquanto ainda compara valores estritamente:
<?php
$wanted = ['x' => 10, 'y' => 20, 'z' => 30];
$current = ['x' => 10, 'Y' => 20, 'z' => 99];
$result = array_udiff_uassoc(
$wanted,
$current,
fn($v1, $v2) => $v1 <=> $v2, // values: strict ordering
fn($k1, $k2) => strcasecmp((string) $k1, (string) $k2) // keys: case-insensitive
);
print_r($result);Saída:
Array
(
[z] => 30
)x => 10 e y => 20 são removidos (current tem o mesmo valor sob uma chave que corresponde sem distinção de maiúsculas e minúsculas), enquanto z => 30 sobrevive porque current tem z => 99 — a chave corresponde, mas o valor 99 !== 30.
Quando usá-la (e o que usar no lugar)
Use array_udiff_uassoc() apenas quando precisar de lógica personalizada para ambas as chaves e os valores. Se precisar de menos, uma variante mais simples é mais rápida de ler e escrever:
| O que você precisa controlar… | Use |
|---|---|
| Apenas valores (callback), chaves ignoradas | array_udiff() |
Valores (callback) + chaves com === | array_udiff_assoc() |
Chaves (callback) + valores com === | array_diff_uassoc() |
| Nenhum — diff simples por valor | array_diff() |
Armadilhas comuns
- Ordem dos argumentos. Os callbacks são os dois últimos argumentos, o de comparação de valor primeiro. Passá-los na ordem errada produz resultados incorretos silenciosamente, sem gerar erro.
- Pelo menos dois arrays. Você deve passar
$array1, pelo menos um outro array e ambos os callbacks — no mínimo cinco argumentos. - Retorne um
int, não umbool. Retornartrue/falsede um comparador funciona por acidente (eles são convertidos para1/0), mas quebra a ordenação. Use<=>ou um-1/0/1explícito. - Chaves são preservadas. O resultado mantém as chaves originais de
$array1; não é re-indexado.
Se callbacks são novidade para você, veja PHP Callback Functions, e para uma revisão sobre arrays em geral, PHP Arrays.
Conclusão
array_udiff_uassoc() é a mais flexível das funções de diferença de array do PHP: compara entradas em chave e valor, e delega ambas as comparações aos seus próprios callbacks. Uma entrada do primeiro array sobrevive apenas quando nenhum outro array a corresponde em ambas as dimensões. Use-a quando as regras de comparação integradas (===, conversão para string) não forem suficientes — por exemplo, chaves sem distinção de maiúsculas e minúsculas, valores sensíveis ao locale, ou comparação de objetos por um campo — e volte a uma variante mais simples de array_diff* quando não precisar de tanto controle.