W3docs

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

Как PHP array_udiff() сравнивает массивы с помощью пользовательского callback и возвращает значения только из первого массива. Примеры с числами и object.

array_udiff() вычисляет разность массивов, сравнивая их значения с помощью callback-функции, которую задаёте вы. Функция возвращает значения из первого массива, которые не найдены ни в одном из остальных массивов. Буква «u» в названии означает user-defined (пользовательская) — в отличие от array_diff(), которая сравнивает значения как string, array_udiff() позволяет вам самим определить, когда два значения считаются «равными».

На этой странице рассматриваются синтаксис функции, принцип работы callback, запускаемые примеры с числами и object, а также распространённые ошибки.

Когда использовать array_udiff()?

Используйте array_udiff(), когда стандартное сравнение в array_diff() недостаточно точное:

  • Object. array_diff() преобразует каждое значение в string. Object без метода __toString() нельзя сравнить таким образом, поэтому нужен callback, проверяющий свойство.
  • Пользовательское равенство. Вы хотите сравнение без учёта регистра, сравнение по одному полю или числовое сравнение с допуском.
  • Смешанные или нормализованные данные. Вы хотите считать "5", 5 и 5.0 одним значением или сравнивать числа с плавающей точкой с округлением.

Если нужно простое сравнение string, предпочтительнее использовать array_diff().

Как работает array_udiff()

Функция принимает два и более массива, причём последним аргументом является callback сравнения. Возвращается array значений из первого массива, которые callback не признаёт равными ни одному значению в последующих массивах. Ключи и порядок из первого массива сохраняются.

Синтаксис

array_udiff(array $array1, array $array2, array ...$arrays, callable $value_compare_func): array
  • array $array1 — массив, значения которого возвращаются («базовый» массив).
  • array $array2 — массив для сравнения.
  • array ...$arrays — любое количество дополнительных массивов для сравнения.
  • callable $value_compare_func — callback сравнения. Всегда является последним аргументом.

Callback сравнения

Callback получает два значения и должен вернуть целое число:

  • число меньше 0, если первое значение «меньше»,
  • 0, если два значения считаются равными,
  • число больше 0, если первое значение «больше».

Возврат 0 означает, что два значения равны, поэтому значение из $array1 исключается из результата, когда callback возвращает 0 при сравнении с каким-либо значением из последующего массива. Результаты < 0 / > 0 позволяют PHP внутренне сортировать значения для эффективного сравнения — важно возвращать их корректно, а не просто 0 или 1. Оператор spaceship (<=>) — самый простой и правильный способ получить это значение.

Пример 1: сравнение двух массивов чисел

В этом примере именованная функция используется как callback для поиска чисел, присутствующих в $array1, но отсутствующих в $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() возвращает 0, когда два значения совпадают, поэтому совпавшие числа (2 и 4) удаляются. В результате сохраняются исходные ключи из $array1:

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

Весь callback можно заменить однострочником с оператором spaceship: fn($a, $b) => $a <=> $b.

Пример 2: сравнение массивов object

Это тот случай, с которым array_diff() не справляется. Здесь мы сравниваем два массива object Product по их id и возвращаем продукты, отсутствующие во втором списке:

<?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;
}

?>

Выводятся продукты, id которых отсутствует в $discontinued:

1: Keyboard
3: Monitor

Поскольку callback сравнивает только id, различия в значениях name не имеют значения — логика сравнения полностью определяется вами.

Что важно помнить

  • Callback всегда является последним аргументом, сколько бы массивов вы ни передали.
  • array_udiff() сравнивает значения. Для сравнения по ключам и значениям одновременно используйте array_udiff_assoc(); для сравнения ключей тоже с помощью callback — array_udiff_uassoc().
  • Возвращайте корректный трёхпозиционный результат (отрицательное / 0 / положительное), а не просто 0 или 1. PHP использует порядок для эффективного сравнения, и небрежный callback может дать неверные результаты.
  • Результат сохраняет ключи и порядок $array1. Вызовите array_values(), если нужен переиндексированный array.
  • В результате могут появляться только значения из первого массива — значения, уникальные для последующих массивов, никогда не возвращаются.

Связанные функции

  • array_diff() — та же идея, но с простым сравнением string.
  • array_udiff_assoc() — callback для значений плюс сравнение ключей.
  • array_uintersect() — эквивалент для пересечения (значения, присутствующие во всех массивах).
  • PHP Arrays и PHP Functions — основы.

Практика

Практика
Какова цель функции array_udiff() в PHP?
Какова цель функции array_udiff() в PHP?
Was this page helpful?