Сравниваем массивы: операторы и функции PHP

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

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

Наиболее эффективное решение: операторы == и ===

Оператор равенства == сравнивает массивы по парам ключ-значение, не учитывая порядок для ассоциативных массивов. Оператор идентичности === дополнительно требует одинакового порядка ключей (для числовых индексов) и строгого равенства типов значений.


$arr1 = ['a' => 1, 'b' => 2];
$arr2 = ['b' => 2, 'a' => 1];
$arr3 = ['a' => 1, 'b' => '2'];

var_dump($arr1 == $arr2);  // true (ключи сопоставлены)
var_dump($arr1 === $arr2); // true (порядок не важен для строковых ключей)
var_dump($arr1 == $arr3);  // true (нестрогое сравнение значений)
var_dump($arr1 === $arr3); // false (строгое сравнение: int vs string)

Php массив добавление (добавить элемент в массив в php)

bool(true)
bool(true)
bool(true)
bool(false)

Php отсортировать массив (отсортировать массив в php)

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

  • Путаница между == и === приводит к неожиданным результатам при наличии разных типов данных в значениях.
  • Для индексированных массивов (числовые ключи) === учитывает порядок элементов, а == - нет (сопоставляет ключи по совпадению).
  • Операторы не работают рекурсивно для многомерных массивов - сравнение вложенных массивов выполняется как сравнение объектов (на равенство ссылок).

Как сравнить только значения массивов, игнорируя ключи?

Если нужно проверить, что массивы содержат одинаковые значения независимо от ключей, используйте array_values() для нормализации массива или функцию array_diff().


$arr1 = ['x' => 10, 'y' => 20];
$arr2 = ['y' => 20, 'z' => 10];

// Способ 1: через array_values и ===
$norm1 = array_values($arr1);
$norm2 = array_values($arr2);
sort($norm1); sort($norm2); // если порядок не важен
var_dump($norm1 === $norm2);

// Способ 2: array_diff (находит отсутствующие значения)
$diff = array_diff($arr1, $arr2);
if (empty($diff)) {
    echo "Массивы содержат одинаковые значения";
}

Php перебор массива (перебрать массив в php)

bool(true)
Массивы содержат одинаковые значения

Php конец массива (получить последний элемент массива в php)

Возможные проблемы:

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

Как найти различия между массивами (какие элементы отсутствуют в другом)?

Функция array_diff вычисляет разность массивов по значениям. Чтобы учитывать и ключи, используйте array_diff_assoc.


$arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
$arr2 = ['a' => 1, 'b' => 2, 'd' => 4];

$diffValues = array_diff($arr1, $arr2);
$diffAssoc  = array_diff_assoc($arr1, $arr2);

print_r($diffValues);  // ['c' => 3] (значение 3 отсутствует в $arr2)
print_r($diffAssoc);   // ['c' => 3, 'd' => 4? Нет, только 'c' => 3, так как 'd' => 4 есть в $arr2, но не в $arr1]

посчитать массив php (посчитать элементы массива в php)

Array
(
    [c] => 3
)
Array
(
    [c] => 3
)

преобразовать массив в строку php (преобразовать массив в строку в php)

Ошибки:

  • Функции работают только с одномерными массивами; для многомерных требуется рекурсивная обработка.
  • Порядок аргументов важен: array_diff($a, $b) возвращает элементы из $a, которых нет в $b.

Как найти общие элементы двух массивов?

Используйте array_intersect (по значениям) или array_intersect_assoc (с учётом ключей).


$arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
$arr2 = ['b' => 2, 'c' => 30, 'd' => 3];

$intersect = array_intersect($arr1, $arr2);
$intersectAssoc = array_intersect_assoc($arr1, $arr2);

print_r($intersect);      // ['b' => 2, 'c' => 3] (значение 3 общее, ключи разные)
print_r($intersectAssoc); // ['b' => 2] (только полное совпадение ключа и значения)

наличие в массиве php (проверить наличие элемента в массиве в php)

Array
(
    [b] => 2
    [c] => 3
)
Array
(
    [b] => 2
)

Php разбить строку на массив (разбить строку на массив в php)

Проблемы:

  • Если в массивах есть дублирующиеся значения, функция вернёт только одно вхождение.
  • Для многомерных массивов требуется рекурсивный аналог (array_uintersect с пользовательской функцией).

Как сравнить многомерные массивы (рекурсивно)?

Встроенные операторы == и === сравнивают многомерные массивы нерекурсивно - они сравнивают только верхний уровень, а вложенные массивы рассматриваются как объекты. Для рекурсивного сравнения применяют пользовательскую функцию или преобразование в строку через json_encode.


function recursiveCompare($a, $b) {
    return serialize($a) === serialize($b);
}

$arr1 = ['a' => [1, 2], 'b' => 3];
$arr2 = ['a' => [1, 2], 'b' => 3];
$arr3 = ['a' => [2, 1], 'b' => 3]; // порядок во вложенном отличается

var_dump(recursiveCompare($arr1, $arr2)); // true
var_dump(recursiveCompare($arr1, $arr3)); // false (разный порядок)

Php сравнить массивы (сравнить массивы в php)

bool(true)
bool(false)

удалить пустые массивы php (удалить пустые массивы из массива в php)

Недостатки и ошибки:

  • Сериализация чувствительна к порядку ключей и типу данных, что иногда нежелательно.
  • json_encode теряет информацию о типе (например, integer превращается в число в строке). Для строгого сравнения используйте serialize.
  • Большие массивы замедляют работу из-за преобразования в строку.

Как сравнить массивы с помощью пользовательской функции?

Функции array_udiff и array_uintersect позволяют задать свою callback-функцию для сравнения значений. Это удобно, если нужно, например, сравнивать объекты или строки без учёта регистра.


$arr1 = ['apple', 'Banana', 'cherry'];
$arr2 = ['Banana', 'cherry', 'Apple'];

$diff = array_udiff($arr1, $arr2, function($a, $b) {
    return strcasecmp($a, $b);
});
print_r($diff); // ['apple'] (регистронезависимое сравнение)
Array
(
    [0] => apple
)

Важно:

  • Функция должна возвращать 0, если значения равны, отрицательное или положительное число - иначе.
  • Для сравнения по ключам есть array_diff_uassoc и array_intersect_uassoc.

Как проверить, что массивы содержат одни и те же значения независимо от порядка?

Отсортируйте оба массива (например, с помощью sort() или asort() для сохранения ключей) и затем используйте оператор === или ==.


$arr1 = [3, 1, 2];
$arr2 = [1, 2, 3];

$copy1 = $arr1;
$copy2 = $arr2;
sort($copy1);
sort($copy2);
var_dump($copy1 === $copy2); // true
bool(true)

Ошибки:

  • Сортировка по умолчанию изменяет индексы (для sort), что может быть неприемлемо для ассоциативных массивов. Используйте asort для сохранения ключей.
  • Если в массиве есть вложенные массивы, сортировка может работать некорректно.

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

Рекурсивное сравнение с пользовательской callback-функцией

Следующий пример демонстрирует рекурсивное сравнение двух многомерных массивов с возможностью задать свою функцию сравнения для листовых значений.

Пример

function recursiveCompareUser($a, $b, $callback) {
    if (is_array($a) && is_array($b)) {
        if (count($a) != count($b)) return false;
        foreach ($a as $key => $value) {
            if (!array_key_exists($key, $b)) return false;
            if (!recursiveCompareUser($value, $b[$key], $callback)) return false;
        }
        return true;
    } else {
        return $callback($a, $b);
    }
}

$arr1 = ['data' => ['id' => 1, 'name' => 'John']];
$arr2 = ['data' => ['id' => '1', 'name' => 'JOHN']];

$result = recursiveCompareUser($arr1, $arr2, function($x, $y) {
    return strtolower((string)$x) === strtolower((string)$y);
});

var_dump($result); // true (регистронезависимое сравнение строк)
bool(true)

Сравнение с помощью array_map и array_filter

Можно сопоставить элементы двух массивов по ключам и отфильтровать несовпадения.

Пример

$arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
$arr2 = ['a' => 1, 'b' => 5, 'd' => 3];

$commonKeys = array_intersect_key($arr1, $arr2);
$diff = array_filter(
    array_map(function($v1, $v2) { return $v1 != $v2 ? $v1 : null; }, $commonKeys, array_intersect_key($arr2, $arr1)),
    function($v) { return !is_null($v); }
);
print_r($diff); // ['b' => 2]
Array
(
    [b] => 2
)

Использование spaceship-оператора для сортированного сравнения

Оператор <=> (космический корабль) удобен в пользовательских функциях сортировки и сравнения. Пример - проверка, являются ли два массива аналогами (имеют одинаковые пары ключ-значение, порядок не важен) с сортировкой по ключам.

Пример

$arr1 = ['x' => 10, 'y' => 20];
$arr2 = ['y' => 20, 'x' => 10];

uksort($arr1, function($a, $b) { return $a <=> $b; });
uksort($arr2, function($a, $b) { return $a <=> $b; });

var_dump($arr1 === $arr2); // true
bool(true)

Глубокое сравнение с обработкой объектов и рекурсивных ссылок

При сравнении массивов, содержащих объекты или рекурсивные ссылки, простые методы (serialize) вызовут ошибку. Ниже - защищённая рекурсивная функция, которая обрабатывает объекты через метод сравнения или приведение к строке.

Пример

function safeDeepCompare($a, $b, &$seen = []) {
    if ($a === $b) return true;
    if (gettype($a) !== gettype($b)) return false;
    if (is_array($a) && is_array($b)) {
        if (count($a) !== count($b)) return false;
        foreach ($a as $key => $value) {
            if (!array_key_exists($key, $b)) return false;
            if (!safeDeepCompare($value, $b[$key], $seen)) return false;
        }
        return true;
    }
    if (is_object($a) && is_object($b)) {
        // Используем метод equals, если он есть, иначе сравнение свойств
        if (method_exists($a, 'equals')) return $a->equals($b);
        return safeDeepCompare(get_object_vars($a), get_object_vars($b), $seen);
    }
    return false;
}

$obj1 = new stdClass();
$obj1->value = 42;
$arr1 = ['obj' => $obj1];
$arr2 = ['obj' => $obj1];

var_dump(safeDeepCompare($arr1, $arr2)); // true (один и тот же объект)
bool(true)

Эффективное сравнение больших массивов с помощью hash-сумм

Если массивы очень большие, можно вычислить хеш (например, md5 от сериализованного представления) и сравнить строки. Этот способ быстрее, чем поэлементное сравнение, но не подходит, если нужна информация о различиях.

Пример

$arr1 = range(1, 100000);
$arr2 = range(1, 100000);
shuffle($arr2); // меняем порядок

$hash1 = md5(serialize($arr1));
$hash2 = md5(serialize($arr2));

var_dump($hash1 === $hash2); // false (порядок разный)

// Если порядок не важен, предварительно отсортировать
$copy1 = $arr1;
$copy2 = $arr2;
sort($copy1);
sort($copy2);
$hash1 = md5(serialize($copy1));
$hash2 = md5(serialize($copy2));
var_dump($hash1 === $hash2); // true
bool(false)
bool(true)

Сравнение массивов с использованием array_reduce

array_reduce позволяет написать компактное сравнение на равенство (с учётом ключей).

Пример

$arr1 = ['a' => 1, 'b' => 2];
$arr2 = ['a' => 1, 'b' => 2];

$equal = array_reduce(
    array_keys($arr1),
    function($carry, $key) use ($arr1, $arr2) {
        return $carry && array_key_exists($key, $arr2) && $arr1[$key] === $arr2[$key];
    },
    count($arr1) === count($arr2)
);
var_dump($equal); // true
bool(true)

Сравнить массивы в PHP - comments

En
Php сравнить массивы (php)