Как получить пересечение массивов в PHP: все способы

Раздел: Работа с массивами в PHP -> Операции сравнения массивов

Обзор методов пересечения массивов в PHP

Как получить массив, содержащий только те значения, которые присутствуют в обоих исходных массивах?

Наиболее эффективным решением является использование встроенной функции array_intersect. Она принимает два или более массивов и возвращает массив, состоящий из элементов первого массива, которые присутствуют во всех остальных. Ключи из первого массива сохраняются. Сравнение значений выполняется нестрого (==).

$first = ['яблоко', 'груша', 'слива'];
$second = ['груша', 'апельсин', 'яблоко'];
$result = array_intersect($first, $second);
print_r($result);

Php пересечения массивов (пересечение массивов в php)

Array
(
    [0] => яблоко
    [1] => груша
)

В примере из первого массива взяты значения 'яблоко' и 'груша', так как они есть во втором. Ключи сохранились (0 и 1). Если требуется сравнивать с учётом ключей, используйте array_intersect_assoc.

Типичные проблемы:

  • Приведение типов: Нестрогое сравнение (==) приводит к совпадению строки '1' и числа 1. Для строгого сравнения (===) используйте array_uintersect с пользовательской функцией.
  • Порядок аргументов: Результат содержит элементы только из первого массива с его ключами. Чтобы сохранить ключи второго массива, меняйте местами массивы или используйте другие функции.
  • Многомерные массивы: array_intersect не сравнивает вложенные массивы. Для этого потребуется array_uintersect или рекурсивный обход.

Как найти пересечение с проверкой ключей (array_intersect_assoc)?

Функция array_intersect_assoc учитывает как ключи, так и значения. Она возвращает элементы первого массива, у которых и ключ, и значение присутствуют в других массивах.

$a = ['id' => 1, 'name' => 'Иван'];
$b = ['id' => 1, 'name' => 'Петр'];
$result = array_intersect_assoc($a, $b);
print_r($result); // ['id' => 1]

Значение 'Иван' не совпало с 'Петр', поэтому элемент с ключом 'name' исключён. Данная функция полезна при работе с ассоциативными массивами, где важна полная идентичность пары ключ-значение.

Проблема: разный порядок ключей

array_intersect_assoc сравнивает и порядок ключей. Если ключи в разных массивах расположены по-разному, элемент может быть исключён, даже если пары ключ-значение совпадают. Для игнорирования порядка используйте сначала сортировку или array_intersect с последующей проверкой ключей.

Как пересечь массивы по ключам, игнорируя значения (array_intersect_key)?

Если нужно найти ключи, присутствующие во всех массивах, используется array_intersect_key. Она возвращает элементы первого массива, ключи которых есть во всех остальных массивах, значения при этом не сравниваются.

$arr1 = ['a' => 100, 'b' => 200, 'c' => 300];
$arr2 = ['a' => 1, 'c' => 2, 'd' => 3];
$result = array_intersect_key($arr1, $arr2);
print_r($result); // ['a' => 100, 'c' => 300]

Полезна при слиянии данных из разных источников, когда нужно взять значения из первого массива только по общим ключам.

Как выполнить пересечение с пользовательским сравнением (array_uintersect)?

Когда стандартное сравнение (== или ===) не подходит, применяется array_uintersect. Она принимает функцию обратного вызова, которая сравнивает два значения и возвращает 0, если они равны, или ненулевое значение иначе.

$numbers = [1, 2, 3, 4];
$strings = ['1', '2', '5'];
// Строгое сравнение (===)
$result = array_uintersect($numbers, $strings, function($a, $b) {
    return $a === $b ? 0 : ($a < $b ? -1 : 1);
});
print_r($result); // пустой массив, так как типы разные

Тот же пример без кастомной функции дал бы [1,2] из-за нестрогого сравнения. array_uintersect даёт полный контроль над логикой сравнения, что необходимо для объектов, многомерных массивов или специализированных типов.

Проблема: производительность

Пользовательские функции замедляют работу. Для больших массивов лучше минимизировать количество вызовов или использовать предварительную обработку (например, сериализацию).

Как вручную найти пересечение массивов (foreach + in_array)?

Если требуется дополнительная логика (например, подсчёт вхождений), можно реализовать пересечение вручную. Самый простой способ – пройти по первому массиву и проверить наличие каждого элемента во втором с помощью in_array.

$first = [10, 20, 30, 40];
$second = [20, 40, 50];
$result = [];
foreach ($first as $value) {
    if (in_array($value, $second)) {
        $result[] = $value;
    }
}
print_r($result); // [20, 40]

Этот метод гибкий, но медленный (O(n*m)). Для больших массивов эффективнее использовать array_intersect.

Проблема: дубликаты

Если в первом массиве есть повторяющиеся значения, в результат попадут все их копии. array_intersect также сохраняет дубликаты, но с той же логикой. Для удаления дубликатов примените array_unique.

Как пересечь более двух массивов?

Все функции семейства array_intersect* допускают произвольное количество аргументов. Достаточно передать их через запятую.

$a = [1, 2, 3, 4];
$b = [2, 3, 5];
$c = [2, 4, 6];
$result = array_intersect($a, $b, $c);
print_r($result); // [2]

Только значение 2 присутствует во всех трёх массивах. Обратите внимание, что результат берётся из первого массива.

Как сохранить только значения из пересечения без ключей?

После использования array_intersect ключи остаются от первого массива, что может быть неудобно. Для переиндексации используют array_values.

$first = ['a' => 1, 'b' => 2, 'c' => 3];
$second = ['x' => 2, 'y' => 3];
$intersect = array_intersect($first, $second);
$result = array_values($intersect);
print_r($result); // [2, 3]

Теперь массив имеет числовые индексы, начиная с 0.

Расширенные примеры пересечения массивов

Пример 1. Пересечение многомерных массивов с помощью сериализации

Если нужно найти общие вложенные массивы, можно сериализовать каждую запись и затем применить стандартное пересечение.

Пример
$users1 = [
    ['id' => 1, 'name' => 'Анна'],
    ['id' => 2, 'name' => 'Борис']
];
$users2 = [
    ['id' => 2, 'name' => 'Борис'],
    ['id' => 3, 'name' => 'Виктор']
];
$serialized1 = array_map('serialize', $users1);
$serialized2 = array_map('serialize', $users2);
$intersect = array_intersect($serialized1, $serialized2);
$result = array_map('unserialize', $intersect);
print_r($result); // [1 => ['id' => 2, 'name' => 'Борис']]
Array
(
    [1] => Array
        (
            [id] => 2
            [name] => Борис
        )
)

Пример 2. Использование array_uintersect для сравнения объектов по свойству

Пример
class Product {
    public $id;
    public function __construct($id) {
        $this->id = $id;
    }
}
$list1 = [new Product(1), new Product(2), new Product(3)];
$list2 = [new Product(2), new Product(3), new Product(4)];
$result = array_uintersect($list1, $list2, function($a, $b) {
    return $a->id <=> $b->id;
});
print_r($result); // оба объекта с id 2 и 3
Array
(
    [1] => Product Object ([id] => 2)
    [2] => Product Object ([id] => 3)
)

Пример 3. Пересечение с сохранением ключей из второго массива

Для этого сначала меняют местами массивы или применяют комбинацию функций.

Пример
$first = ['a' => 1, 'b' => 2];
$second = ['x' => 2, 'y' => 3];
// Обычное пересечение сохраняет ключи 'b' из первого
$intersect = array_intersect($first, $second); // ['b' => 2]
// Чтобы сохранить ключи второго массива, инвертируем значения
$flipped = array_flip($second);
$commonValues = array_intersect($first, array_keys($flipped));
$result = array_intersect_key($flipped, array_flip($commonValues));
$result = array_flip($result);
print_r($result); // ['x' => 2]
Array
(
    [x] => 2
)

Пример 4. Пересечение с использованием callback-фильтрации

Пример
$a = [10, 20, 30, 40];
$b = [15, 25, 35];
// Найти элементы из $a, которые больше любого элемента из $b
$result = array_uintersect($a, $b, function($x, $y) {
    // Возвращаем 0, если $x больше $y - нестандартная логика
    return ($x > $y) ? 0 : -1;
});
print_r($result); // все элементы $a, так как каждый больше 15

Пример 5. Пересечение с помощью array_filter и in_array (аналог ручного метода, но функциональный)

Пример
$a = [1, 2, 3, 4];
$b = [2, 4, 6];
$result = array_filter($a, function($value) use ($b) {
    return in_array($value, $b);
});
print_r($result); // [1 => 2, 3 => 4] - ключи сохраняются
Array
(
    [1] => 2
    [3] => 4
)

Пример 6. Комбинированное использование array_intersect_key и array_intersect для строгого контроля

Пример
$a = ['x' => 10, 'y' => 20, 'z' => 30];
$b = ['y' => 20, 'z' => 25, 'w' => 30];
// Сначала пересечение по ключам
$byKey = array_intersect_key($a, $b); // ['y' => 20, 'z' => 30]
// Затем из них пересечение по значениям
$final = array_intersect_assoc($byKey, $b); // ['y' => 20]
print_r($final); // только полное совпадение ключа и значения
Array
(
    [y] => 20
)

Пересечение массивов в PHP - comments

En
Php пересечения массивов (php)