PHP сравнить массив

Есть ли способ сравнить массивы в php с помощью встроенной функции, если не делать какой-то цикл?

$a1 = array(1,2,3);
$a2 = array(1,2,3);

if (array_are_same($a1, $a2)) {
    // code here
}

Кстати, значения массива не всегда будут в одном и том же порядке.


person Community    schedule 23.05.2009    source источник
comment
Что означает то же самое; Вы имеете в виду, что они содержат одни и те же элементы в том же порядке или просто содержат одни и те же элементы? Для первого ответ karim79 правильный; в противном случае будет достаточно ответов, защищающих обычный ==.   -  person Rob    schedule 23.05.2009
comment
А как насчет повторяющихся значений?   -  person hakre    schedule 14.07.2013
comment
Лучший ответ (наиболее полный) кажется от @hakre: stackoverflow.com/questions/901815/php-compare-array/ ‹‹ Это следует выбрать как правильный ответ на это имхо.   -  person Jon L.    schedule 27.05.2014


Ответы (17)


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

!array_diff($a, $b) && !array_diff($b, $a);

Это дает TRUE, если оба массива имеют одинаковые значения (после жонглирования типами). FALSE иначе. Примеры:

function array_equal_values(array $a, array $b) {
    return !array_diff($a, $b) && !array_diff($b, $a);
}

array_equal_values([1], []);            # FALSE
array_equal_values([], [1]);            # FALSE
array_equal_values(['1'], [1]);         # TRUE
array_equal_values(['1'], [1, 1, '1']); # TRUE

Как показывает этот пример, array_diff исключает ключи массива из уравнения и не заботится ни о порядке значений, ни о том, дублируются значения или нет.


Если дублирование должно иметь значение, это становится более сложным. Что касается «простых» значений (работают только строковые и целочисленные значения), array_count_values() вступает в игру для сбора информации. о том, какое значение, как часто внутри массива. Эту информацию можно легко сравнить с ==:

array_count_values($a) == array_count_values($b);

Это дает TRUE, если оба массива имеют одинаковые значения (после жонглирования типами) за одинаковое количество времени. FALSE иначе. Примеры:

function array_equal_values(array $a, array $b) {
    return array_count_values($a) == array_count_values($b);
}

array_equal_values([2, 1], [1, 2]);           # TRUE
array_equal_values([2, 1, 2], [1, 2, 2]);     # TRUE
array_equal_values(['2', '2'], [2, '2.0']);   # FALSE
array_equal_values(['2.0', '2'], [2, '2.0']); # TRUE

Это можно дополнительно оптимизировать, сначала сравнив количество двух массивов, что относительно дешево, и быстрый тест, чтобы отличить большинство массивов, когда дублирование значений подсчета имеет значение.


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

Это немного больше работы. Однако в конце сравнение такое же, как и раньше:

$count($a) == $count($b);

Разница только в $count:

    $table = [];
    $count = function (array $array) use (&$table) {
        $exit   = (bool)$table;
        $result = [];
        foreach ($array as $value) {
            $key = array_search($value, $table, true);

            if (FALSE !== $key) {
                if (!isset($result[$key])) {
                    $result[$key] = 1;
                } else {
                    $result[$key]++;
                }
                continue;
            }

            if ($exit) {
                break;
            }

            $key          = count($table);
            $table[$key]  = $value;
            $result[$key] = 1;
        }

        return $result;
    };

Это сохраняет таблицу значений, чтобы оба массива могли использовать один и тот же индекс. Также можно выйти досрочно в первый раз, когда во втором массиве появляется новое значение.

Эта функция также может добавить контекст strict с помощью дополнительного параметра. А добавление еще одного дополнительного параметра позволило бы включить поиск дубликатов или нет. Полный пример:

function array_equal_values(array $a, array $b, $strict = FALSE, $allow_duplicate_values = TRUE) {

    $add = (int)!$allow_duplicate_values;

    if ($add and count($a) !== count($b)) {
        return FALSE;
    }

    $table = [];
    $count = function (array $array) use (&$table, $add, $strict) {
        $exit   = (bool)$table;
        $result = [];
        foreach ($array as $value) {
            $key = array_search($value, $table, $strict);

            if (FALSE !== $key) {
                if (!isset($result[$key])) {
                    $result[$key] = 1;
                } else {
                    $result[$key] += $add;
                }
                continue;
            }

            if ($exit) {
                break;
            }

            $key          = count($table);
            $table[$key]  = $value;
            $result[$key] = 1;
        }

        return $result;
    };

    return $count($a) == $count($b);
}

Примеры использования:

array_equal_values(['2.0', '2', 2], ['2', '2.0', 2], TRUE);           # TRUE
array_equal_values(['2.0', '2', 2, 2], ['2', '2.0', 2], TRUE);        # TRUE
array_equal_values(['2.0', '2', 2, 2], ['2', '2.0', 2], TRUE, FALSE); # FALSE
array_equal_values(['2'], ['2'], TRUE, FALSE);                        # TRUE
array_equal_values([2], ['2', 2]);                                    # TRUE
array_equal_values([2], ['2', 2], FALSE);                             # TRUE
array_equal_values([2], ['2', 2], FALSE, TRUE);                       # FALSE
person hakre    schedule 14.07.2013
comment
отличный ответ, кажется наиболее полным здесь. - person Jon L.; 27.05.2014
comment
Этот ответ не работает, если один массив имеет значение дважды. И другой массив также имеет это значение дважды. - person Case; 22.01.2016
comment
@Iscariot: Это действительно интересный сценарий, который не рассматривается. Ответ, скорее всего, будет коротким для сравнения дублирующихся значений, поскольку вопрос также не охватывает их. Возможна и другая дифференциация: повторяющиеся (n-time) значения также должны совпадать n-times или 1:n-times. - person hakre; 23.01.2016

@Cleanshooter извините, но это не делает того, что ожидается: (так же, как и array_diff, упомянутый в этом контексте)

$a1 = array('one','two');
$a2 = array('one','two','three');

var_dump(count(array_diff($a1, $a2)) === 0); // returns TRUE

(аннотация: вы не можете использовать пусто для функций до PHP 5.5) в этом случае результат верен, хотя массивы разные.

array_diff [...] Возвращает массив, содержащий все записи из array1, которых нет ни в одном из других массивов.

что не означает, что array_diff что-то вроде: array_get_all_differences. Объясняется математическими наборами, которые он вычисляет:

{'one','two'} \ {'one','two','three'} = {}

что означает что-то вроде всех элементов из первого набора без всех элементов из второго набора, которые есть в первом наборе. Чтобы

var_dump(array_diff($a2, $a1));

вычисляет до

array(1) { [2]=> string(5) "three" } 

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

надеюсь это поможет :)

person pscheit    schedule 17.01.2012

Также вы можете попробовать так:

if(serialize($a1) == serialize($a2))
person Murz    schedule 06.11.2013

Просто проверьте $a1 == $a2 -- что в этом не так?

person Alex Martelli    schedule 23.05.2009
comment
Это также требует, чтобы ключи массива также совпадали, как в примере сравнения массивов, найденном в документах PHP: php.net/manual/en/language.operators.comparison.php - person Jon L.; 11.05.2011
comment
С подсказкой Джона Л. Думаю, лучше всего сравнивать значения массива: array_values($a1) == array_values($a2) - person Tyron; 15.01.2013
comment
... а также порядок должен быть таким же. В зависимости от того, что желательно, вы можете сначала отсортировать массивы. - person NickSoft; 24.11.2013

array_intersect() возвращает массив, содержащий все общие значения.

person moonw    schedule 20.11.2011

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

function arrays_are_same($array1, $array2) {
    sort($array1);
    sort($array2);
    return $array1==$array2;
}

Таким образом, для...

    $array1 = array('audio', 'video', 'image');
    $array2 = array('video', 'image', 'audio');

arrays_are_same($array1, $array2) вернется TRUE

person chichilatte    schedule 21.08.2012
comment
Порядок массива не имеет значения, согласно примеру № 1 на php. net/manual/en/language.operators.comparison.php - person Tyron; 15.01.2013
comment
Хм? Если вы сделаете var_dump(array(1,2,3) == array(3,2,1));, вы получите bool(false). То же самое и с Примером №1: var_dump(standard_array_compare(array(1,2,3), array(3,2,1))); возвращает int(-1). - person chichilatte; 19.02.2013

Вывод из комментария здесь:

Сравнение значений массива при равенстве (после жонглирования типами) и только в том же порядке:

array_values($a1) == array_values($a2)

Сравнение одинаковых значений массива (после жонглирования типами) и в том же порядке и одинаковых ключей массива и в том же порядке:

array_values($a1) == array_values($a2) && array_keys($a1) == array_keys($a2)
person Tyron    schedule 15.01.2013
comment
Ух ты. Я перехожу с С++ на PHP. Большая разница. На PHP лучший подходящий ответ скрыт под 5 экранами, а как насчет того, чтобы просто использовать 'это здесь, а? На С++ все, что я вижу, технически хорошо, самый правильный ответ должен быть таким! - person Scott; 12.05.2013
comment
если вы хотите просто сравнить оба ключа и значения, почему бы вам не использовать $a1 == $a2 - person NickSoft; 24.11.2013

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

sort($a1);
sort($a2);
echo (($a1==$a2) ? "arrays are equal" : "arrays are not equal");
person CJ Ramki    schedule 07.08.2013
comment
Этот точный способ уже был предложен в этом другом ответе, на самом деле нет смысла повторять его. - person Shadow Wizard Wearing Mask V2; 13.08.2013

Если вы хотите найти какой-то массив внутри большого массива массивов (>10 КБ), то намного быстрее сравнивает сериализованные массивы (сохраненные в кеше). Пример из работы с URL:

/**
@return array
*/
function createCache()
{
    $cache = [];
    foreach ($this->listOfUrl() as $url => $args)
    {
        ksort($args);
        $cache['url'][$url] = $args;
        $cache['arr'][crc32(serialize($args))] = $url;
    }
    return $cache;
}

/**
@param array $args
@return string
*/
function searchUrl($args)
{
    ksort($params);
    $crc = crc32(serialize($params));        
    return isset($this->cache['arr'][$crc]) ? $this->cache['arr'][$crc] : NULL;                
} 

/**
@param string $url
@return array
*/
function searchArgs($url)
{
    return isset($this->cache['url'][$url]) ? $this->cache['url'][$url] : NULL;
}
person revoke    schedule 02.01.2017

убедитесь, что количество пересечений совпадает с обоими исходными массивами

$intersections = array_intersect($a1, $a2);
$equality = (count($a1) == count($a2)) && (count($a2) == count($intersections)) ? true : false;
person rcourtna    schedule 17.04.2013

Сравните значения двух массивов:

$a = array(1,2,3);
$b = array(1,3,2);

if (array_diff($a, $b) || array_diff($b, $a)) {
    echo 'Not equal';
}else{
    echo 'Equal';
}
person 1Rhino    schedule 12.05.2013

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

$mag = '{"1":"1","2":"2","3":"3","4":"3"}';
$mag_evo = '1|2|3';

$test1 = array_values(json_decode($mag, true));
$test2 = array_values(explode('|', $mag_evo));

if($test1 == $test2) {
    echo 'true';
}

Это не будет эхо-сигналом true, так как $mag имеет 2 значения в массиве, равные 3.

Это работает лучше всего, если вы заботитесь только о значениях и ключах и не заботитесь о дублировании. $mag = '{"1":"1","2":"2","3":"3","4":"3"}'; $mag_evo = '1|2|3';

$test1 = json_decode($mag, true);
$test2 = explode('|', $mag_evo);

// There is no difference in either array.  
if(!array_diff($test1, $test2) && !array_diff($test2, $test1)) { 
    echo 'true';
}

Это вернет true, так как все значения находятся в обоих массивах, но, как отмечалось ранее, не заботится о дублировании.

person Case    schedule 22.01.2016

это простой способ получить разницу:

$array1 = [40,10,30,20,50];
$array2 = [10,30];
$result = array_filter(
                       $array1,
                       function($var) use($array2){
                                if(in_array($var, $array2)){
                                   return $var;
                                }
                         }
             );
print_r($result); //Array ( [0] => 10 [1] => 30 )
person Ibnul Husainan    schedule 19.10.2020

попробуй это :

$array1 = array("street" => array("Althan"), "city"   => "surat", "state"  => "guj", "county" => "india");
        $array2  = array("street" => array("Althan"), "city"   => "surat", "state"  => "guj", "county" => "india");

    if (array_compare($array1, $array2))
    {
             echo "<pre>";
             print_r("succsses..!");
             echo "</pre>";
             exit;

    }
    else
    {
            echo "<pre>";
            print_r("Faild..!");
            echo "</pre>";
            exit;
    }

    function array_compare($op1, $op2)
    {

            foreach ($op1 as $key => $val)
            {
                    if (is_array($val))
                    {
                            if (array_compare($val, $op2[$key]) === FALSE)
                                    return false;
                    }
                    else
                    {

                            if (!array_key_exists($key, $op2))
                            {
                                    return false; // uncomparable
                            }
                            elseif ($val < $op2[$key])
                            {
                                    return false;
                            }
                            elseif ($val > $op2[$key])
                            {
                                    return false;
                            }
                    }
            }
            return true; // $op1 == $op2
    }
person Chintan    schedule 23.05.2012

Насколько я могу судить, нет ни одной встроенной функции, которая сделает это за вас, например:

if (count($a) == count($b) && (!count(array_diff($a, $b))) {
  // The arrays are the same
}

Должен сделать трюк

person pnomolos    schedule 02.11.2012

person    schedule
comment
Это также требует, чтобы ключи массива также совпадали, как показано в примере сравнения массивов, который можно найти в документации по PHP: php.net/manual/en/language.operators.comparison.php - person Jon L.; 11.05.2011
comment
@ДжонЛ. if ( array_values( $a ) == array_values( $b ) {} ?? - person Eric Holmes; 26.05.2014
comment
@EricHolmes, как отмечено в комментариях к другому ответу, работает только в том случае, если порядок тот же: title="сравните массив php">stackoverflow.com/questions/901815/php-compare-array/ - person Jon L.; 27.05.2014
comment
Посмотрите историю редактирования вопроса, и вы поймете, почему ответ правильный в соответствии с исходным вопросом, опубликованным 23 мая 2009 г. в 16:05. Вопрос был отредактирован кем-то другим, а не исследователем 14 июля 2013, в 11:43, чтобы добавить, кстати, значения массива не всегда будут в одном и том же порядке. - person Alan Haggai Alavi; 28.05.2014

person    schedule
comment
array_intersect не будет сравнивать порядок значений. но сравнение размера массива перед фактическим сравнением может быть хорошей оптимизацией. Также пересечение массива не будет хорошо работать для повторяющихся значений - array_intersect(array(value1, value1, value2), array(value1, value2, value2)) - это скажет, что 2 массива одинаковы, но это не так. - person NickSoft; 24.11.2013