PHP - проверить, равны ли два массива


280

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

Использование, !==как предложено пользователем, я ожидаю, что следующее напечатало бы ввод, если хотя бы один элемент в массиве (ах) отличается, но на самом деле это не так.

if (($_POST['atlOriginal'] !== $oldAtlPosition) 
    or ($_POST['atl'] !== $aext) 
    or ($_POST['sidesOriginal'] !== $oldSidePosition) 
    or ($_POST['sidesOriginal'] !== $sideext)) {

    echo "enter";
}

17
Вы используете =слишком много, это должно быть !==или!=
Jeroen

29
Просто для записи (поскольку мое редактирование было изменено на «пользователь»), это «пользователь»: english.stackexchange.com/questions/105116/…
teynon

7
['a'] == [0]есть true. Ну, это всего лишь PHP.
Давид Хорват

2
@ DávidHorváth это действительно странно, хорошая практика это всегда использовать ===
AFA Med

1
@ DávidHorváth, свободное сравнение не только в PHP. Если вы посмотрите на JS, вы будете удивлены. Просто не используйте, пока не поймете вещи лучше.
рябенко-про

Ответы:


510
$arraysAreEqual = ($a == $b); // TRUE if $a and $b have the same key/value pairs.
$arraysAreEqual = ($a === $b); // TRUE if $a and $b have the same key/value pairs in the same order and of the same types.

Смотрите Операторы Массива .

РЕДАКТИРОВАТЬ

Оператор неравенства - это, в !=то время как неединичный оператор !==должен соответствовать оператору равенства ==и тождественному оператору ===.


79
Примечание: этот подход работает и для многомерных массивов (раньше это не было так очевидно для меня).
Трейдер

5
PS: решение заключается в использовании array_values($a)==array_values($b)... Другая обычная проблема связана с уникальными значениями, поэтому помните, что существуют array_unique().
Питер Краусс

13
Этот ответ неверен. ==работает независимо от порядка только для типичных словарей типа [1 => 'a', 2 => 'b']. Для например [1 => 'a', 2 => 'b'] == [2 => 'b', 1 => 'a']. Для индексированных массивов вроде ['a', 'b'] ==не работает, как указано. Для например ['a', 'b'] != ['b', 'a'].
Nawfal

37
@nawfal: Ваше предположение неверно. ['a', 'b']это массив [0 => 'a', 1 => 'b'], а ['b', 'a']это массив [0 => 'b', 1 => 'a']. Вот почему у них нет тех же пар ключ / значение, как указано в моем ответе, и поэтому ==между ними не работает.
Стефан Гериг

29
@StefanGehrig О, ты прав. Я оставлю свой комментарий как таковой, чтобы сделать мою глупость очевидной :)
nawfal

88

По этой странице .

ПРИМЕЧАНИЕ . Принятый ответ работает для ассоциативных массивов, но не работает должным образом с индексированными массивами (поясняется ниже). Если вы хотите сравнить любой из них, используйте это решение. Кроме того, эта функция может не работать с многомерными массивами (из-за природы функции array_diff).

Тестирование двух индексированных массивов, элементы которых находятся в разном порядке, с использованием $a == $bили $a === $bнеудачей, например:

<?php
    (array("x","y") == array("y","x")) === false;
?>

Это потому, что выше означает:

array(0 => "x", 1 => "y")против array(0 => "y", 1 => "x").

Чтобы решить эту проблему, используйте:

<?php
function array_equal($a, $b) {
    return (
         is_array($a) 
         && is_array($b) 
         && count($a) == count($b) 
         && array_diff($a, $b) === array_diff($b, $a)
    );
}
?>

Добавлено сравнение размеров массивов (предложено super_ton), так как это может улучшить скорость.


2
Внимание: не работает
должным образом

8
Приведенный выше комментарий является ложным. Если $ b имеет все элементы, которые имеет $ a, плюс некоторые дополнительные, два массива не равны, но приведенный выше код скажет, что они есть.
Гхола

1
возможно, стоит добавить счетчик ($ a) == счетчик ($ b)
Стефан

1
@super_ton: да, перед звонком array_diffможно было бы ускорить сравнение. Я добавлю это. Спасибо
Лепе

3
К сожалению, в некоторых случаях это не работает, например, я протестировал следующий случай, $a = [1, 2, 2]; $b = [2, 1, 1];и он вернулся true, но два массива, очевидно, не совпадают.
AwesomeGuy

33

Попробуй сериализовать. Это также проверит вложенные подмассивы.

$foo =serialize($array_foo);
$bar =serialize($array_bar);
if ($foo == $bar) echo "Foo and bar are equal";

7
Проблематично, если ключи и значения перемещаются, как при сравнении. Однако, если предположить, что они будут на 100% одинаковыми, это самый простой и простой способ проверить глубокое равенство!
Кевин Пено

1
Я думаю, это лучшее решение! Он может сравнивать многомерные и ассоциативные массивы, если они были ранее отсортированы!
Рафаэль Мони

14

Краткое решение, которое работает даже с массивами, ключи которых даны в другом порядке:

public static function arrays_are_equal($array1, $array2)
{
    array_multisort($array1);
    array_multisort($array2);
    return ( serialize($array1) === serialize($array2) );
}

3
Вероятно, лучший ответ до сих пор, большинство ответов либо не совпадают, если ключи смещены, или это многомерный массив.
AwesomeGuy

Хороший выбор! Но обратите внимание, что этот метод использует строгое сравнение типов, поэтому, если вы хотите сравнить [1,2,3] и ['1', '2', '3'], результат будет ложным.
ChronoExp

11

Сравните их как другие значения:

if($array_a == $array_b) {
  //they are the same
}

Вы можете прочитать обо всех операторах массива здесь: http://php.net/manual/en/language.operators.array.php. Например, обратите внимание, что ===также проверяется, что типы и порядок элементов в массивах одинаковы.


5
Или в ===зависимости от желаемого поведения.
Мэтью Флэшен

9

!===не будет работать, потому что это синтаксическая ошибка. Правильный путь !==(не три "равных" символа)


5
if (array_diff($a,$b) == array_diff($b,$a)) {
  // Equals
}

if (array_diff($a,$b) != array_diff($b,$a)) {
  // Not Equals
}

Из моего pov лучше использовать array_diff, чем array_intersect, потому что при проверках такого типа возвращаемые различия обычно меньше, чем сходства, поэтому преобразование bool требует меньше памяти.

Редактировать Обратите внимание, что это решение предназначено для простых массивов и дополняет опубликованное выше == и ===, которое действительно только для словарей.


4

array_diff - вычисляет разницу массивов

http://php.net/manual/en/function.array-diff.php

array array_diff ( array $array1 , array $array2 [, array $... ] )

Сравнивает array1с одним или несколькими другими массивами и возвращает значения array1, которых нет ни в одном из других массивов.


4
ОП хочет «проверить, равны ли два массива». array_diffне могу тебе этого сказать. Попробуй array_diff([1, 2], [1, 2, 'hello']).
марта

3

Другой метод проверки равенства независимо от порядка значений работает с использованием http://php.net/manual/en/function.array-intersect.php , например так:

$array1 = array(2,5,3);
$array2 = array(5,2,3);
if($array1 === array_intersect($array1, $array2) && $array2 === array_intersect($array2, $array1)) {
    echo 'Equal';
} else {
    echo 'Not equal';
}

Вот версия, которая работает также с многомерными массивами, используя http://php.net/manual/en/function.array-uintersect.php :

$array1 = array(
    array(5, 2),
    array(3, 6),
    array(2, 9, 4)
);
$array2 = array(
    array(3, 6),
    array(2, 9, 4),
    array(5, 2)
);

if($array1 === array_uintersect($array1, $array2, 'compare') && $array2 === array_uintersect($array2, $array1, 'compare')) {
    echo 'Equal';
} else {
    echo 'Not equal';
}

function compare($v1, $v2) {
    if ($v1===$v2) {
        return 0;
    }
    if ($v1 > $v2) return 1;
    return -1;
}

3
function compareIsEqualArray(array $array1,array $array):bool
{

   return array_diff($array1,$array2)==[];

}

2
Полезно объяснить, что делает пример кода. Это также работает для многомерных массивов?
k0pernikus

1
array_diff получить другой элемент из массива, если array_diff вернуть пустой массив, два массива равны
dılo sürücü

2

Один из способов: (реализация «считается равным» для http://tools.ietf.org/html/rfc6902#section-4.6 )

Этот способ позволяет ассоциативные массивы, члены которых упорядочены по-разному - например, они будут считаться равными на всех языках, кроме php :)

// recursive ksort
function rksort($a) {
  if (!is_array($a)) {
    return $a;
  }
  foreach (array_keys($a) as $key) {
    $a[$key] = ksort($a[$key]);
  }
  // SORT_STRING seems required, as otherwise
  // numeric indices (e.g. "0") aren't sorted.
  ksort($a, SORT_STRING);
  return $a;
}


// Per http://tools.ietf.org/html/rfc6902#section-4.6
function considered_equal($a1, $a2) {
  return json_encode(rksort($a1)) === json_encode(rksort($a2));
}

1
Я считаю, что это должно быть:$a[$key] = rksort($a[$key]);
Pinkeen

2

Синтаксическая проблема в ваших массивах

$array1 = array(
    'a' => 'value1',
    'b' => 'value2',
    'c' => 'value3',
 );

$array2 = array(
    'a' => 'value1',
    'b' => 'value2',
    'c' => 'value3',
 );

$diff = array_diff($array1, $array2);

var_dump($diff); 

2

Вот пример, как сравнить с массивами и узнать, что отличается между ними.

$array1 = ['1' => 'XXX', 'second' => [
            'a' => ['test' => '2'],
            'b' => 'test'
        ], 'b' => ['no test']];

        $array2 = [
            '1' => 'XX',
            'second' => [
                'a' => ['test' => '5', 'z' => 5],
                'b' => 'test'
            ],
            'test'
        ];


        function compareArrayValues($arrayOne, $arrayTwo, &$diff = [], $reversed = false)
        {
            foreach ($arrayOne as $key => $val) {
                if (!isset($arrayTwo[$key])) {
                    $diff[$key] = 'MISSING IN ' . ($reversed ? 'FIRST' : 'SECOND');
                } else if (is_array($val) && (json_encode($arrayOne[$key]) !== json_encode($arrayTwo[$key]))) {
                    compareArrayValues($arrayOne[$key], $arrayTwo[$key], $diff[$key], $reversed);
                } else if ($arrayOne[$key] !== $arrayTwo[$key]) {
                    $diff[$key] = 'DIFFERENT';
                }
            }
        }

        $diff = [];
        $diffSecond = [];

        compareArrayValues($array1, $array2, $diff);
        compareArrayValues($array2, $array1, $diffSecond, true);

        print_r($diff);
        print_r($diffSecond);

        print_r(array_merge($diff, $diffSecond));

Результат:

Array
(
    [0] => DIFFERENT
    [second] => Array
        (
            [a] => Array
                (
                    [test] => DIFFERENT
                    [z] => MISSING IN FIRST
                )

        )

    [b] => MISSING IN SECOND
    [1] => DIFFERENT
    [2] => MISSING IN FIRST
)

1

Используйте функцию php array_diff (array1, array2);

Это вернет разницу между массивами. Если его пусто, то они равны.

пример:

$array1 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3'
 );

$array2 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value4'
 );

$diff = array_diff(array1, array2);

var_dump($diff); 

//it will print array = (0 => ['c'] => 'value4' ) 

Пример 2:

$array1 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3',
 );

$array2 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3',
 );

$diff = array_diff(array1, array2);

var_dump($diff); 

//it will print empty; 

1
Технически, это не возвращает разницу между массивами. В документации говорится: «Сравнивает массив1 с одним или несколькими другими массивами и возвращает значения в массиве1, которых нет ни в одном из других массивов». Итак, если все значения из array1 присутствуют в array2, даже если array2 имеет больше значений, array_diff вернет пустой массив
2pha

Не «печатает ноль», печатает пустой массив (после исправления около десятка синтаксических ошибок). Может быть, вы можете использовать, (count(array_diff($a1, $a2)) + count(array_diff($a2, $a1))) === 0чтобы проверить, равны ли массивы
user9645

Я исправил синтаксис (не ноль пуст, и я смешивал запятые -.-). То, что вы предлагаете, я думаю, это слишком много. Проверить, достаточно ли пустого массива.
Вольфганг Леон

1

Если вы хотите проверить неассоциативные массивы, вот решение:

$a = ['blog', 'company'];
$b = ['company', 'blog'];

(count(array_unique(array_merge($a, $b))) === count($a)) ? 'Equals' : 'Not Equals';
// Equals
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.