W3docs

Функция array_udiff_assoc() в PHP

Как работает array_udiff_assoc() в PHP: сравнение массивов по ключу и callback-функции значений. Синтаксис, примеры и подводные камни.

array_udiff_assoc() сравнивает два или более массивов и возвращает элементы из первого массива, которые отсутствуют в остальных. Её особенность — в способе сравнения: ключи сравниваются встроенной строгой проверкой, а значения — callback-функцией, которую вы передаёте. На этой странице разбирается сигнатура, рассматриваются рабочие примеры (строки, несколько массивов и объекты) и объясняются типичные ошибки.

Синтаксис

array_udiff_assoc(
    array $array,
    array ...$arrays,
    callable $value_compare_func
): array
  • $array — массив, из которого берутся элементы для сравнения. Только его элементы могут попасть в результат.
  • ...$arrays — один или несколько массивов для сравнения с ним. Можно передавать сколько угодно.
  • $value_compare_func — callback-функция, сравнивающая два значения. Она должна возвращать целое число меньше, равное или больше 0, когда первый аргумент соответственно меньше, равен или больше второго — тот же контракт, что используется в usort() и операторе «космический корабль» (<=>).

Функция возвращает новый array из сохранившихся пар ключ/значение из $array. Callback всегда является последним аргументом.

Принцип сравнения

Элемент из первого массива сохраняется, если ни в одном другом массиве нет одновременно того же ключа (сравниваемого внутренне как строки) и значения, которое callback считает равным (возвращает 0). Иными словами:

  • Ключи → строгое встроенное сравнение (отражено в слове assoc в названии).
  • Значения → ваш callback (буква u означает user-defined, пользовательский).

Это главное отличие от array_diff_assoc(), который сравнивает значения через приведение к (string), и от array_udiff(), который полностью игнорирует ключи.

Базовый пример

<?php

function compareArrays($a, $b) {
  if ($a === $b) {
    return 0;
  }
  return ($a > $b) ? 1 : -1;
}

$array1 = array("a" => "red", "b" => "green", "c" => "blue");
$array2 = array("a" => "red", "b" => "blue", "c" => "green");

$result = array_udiff_assoc($array1, $array2, "compareArrays");

print_r($result);

?>

Разбор по ключам:

  • a"red" против "red": ключи совпадают, callback возвращает 0 (равны) → удалён.
  • b"green" против "blue": ключи совпадают, значения различаются → сохранён.
  • c"blue" против "green": ключи совпадают, значения различаются → сохранён.

Вывод:

Array
(
    [b] => green
    [c] => blue
)

Сравнение с несколькими массивами

Можно передать более одного массива для сравнения. Элемент сохраняется, только если его нет ни в одном из остальных массивов. В примере ниже callback сравнивает строки сначала по длине, затем по алфавиту:

<?php

function compareValues($a, $b) {
  return strlen($a) <=> strlen($b) ?: strcmp($a, $b);
}

$current  = ["item1" => "apple", "item2" => "banana", "item3" => "kiwi"];
$baseline = ["item1" => "apple", "item2" => "cherry", "item3" => "kiwi"];

$result = array_udiff_assoc($current, $baseline, "compareValues");

print_r($result);

// Array
// (
//     [item2] => banana
// )

Отличается только item2: "banana" (6 букв) и "cherry" (6 букв) одинаковой длины, поэтому callback переходит к strcmp(), который сообщает о различии. item1 и item3 одинаковы в обоих массивах и удаляются.

Сравнение объектов

Настоящая сила array_udiff_assoc() проявляется, когда значениями являются объекты или массивы — то, что нельзя сравнить простым приведением к строке. Callback определяет смысл «равенства». В примере две корзины товаров сравниваются только по цене, без учёта названия товара:

<?php

class Product {
  public function __construct(public string $name, public float $price) {}
}

function byPrice(Product $a, Product $b): int {
  return $a->price <=> $b->price;
}

$cart = [
  "p1" => new Product("Pen", 1.50),
  "p2" => new Product("Notebook", 3.00),
];

$reference = [
  "p1" => new Product("Pen", 1.50),
  "p2" => new Product("Notebook", 4.25),
];

$diff = array_udiff_assoc($cart, $reference, "byPrice");

foreach ($diff as $key => $product) {
  echo "$key => {$product->name} ({$product->price})\n";
}

// p2 => Notebook (3)

У p1 цена в обоих массивах одинакова, поэтому он удаляется; цена p2 изменилась, значит, он сохраняется.

Подводные камни

  • Callback — последний аргумент, а не второй. Распространённая ошибка — вызов array_udiff_assoc($a, $callback, $b). Правильный порядок: первый массив, затем массивы для сравнения, затем callback.
  • Callback сравнивает значения, но не ключи. Ключи обрабатываются внутренне строгим сравнением; влиять на сопоставление ключей здесь нельзя. Если нужно пользовательское сравнение ключей, используйте array_udiff_uassoc().
  • Возвращайте целое число, а не boolean. Возврат true/false из callback срабатывает случайно (они приводятся к 1/0), но это ненадёжно — возвращайте результат <=> или явное -1/0/1.
  • В результате сохраняются оригинальные ключи из первого массива; переиндексация не выполняется.

Когда использовать

Используйте array_udiff_assoc(), когда важны и ключ, и пользовательское сравнение значений — например, при сравнении двух наборов объектов с ключами, поиске различий без учёта регистра с сохранением идентификаторов или вычислении изменений между предыдущим и текущим состоянием. Если ключи не важны, используйте array_udiff(); если значения — простые скаляры, достаточно более лёгкого array_diff_assoc().

Заключение

array_udiff_assoc() — точный инструмент для поиска различий между массивами, когда важны и ключи, и пользовательская логика сравнения значений. Сочетая строгое сопоставление ключей с управляемым callback-сравнением, можно сравнивать сложные структуры данных — объекты, вложенные массивы, нормализованные строки — без написания вложенных циклов и ручных проверок.

Практика

Практика
Что делает функция 'array_udiff_assoc()' в PHP?
Что делает функция 'array_udiff_assoc()' в PHP?
Was this page helpful?