346

I'd like to check if two arrays are equal. I mean: same size, same index, same values. How can I do that?

Using !== as suggested by a user, I expect that the following would print enter if at least one element in the array(s) are different, but in fact it does not.

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

    echo "enter";
}
izeke
  • 75
  • 8
markzzz
  • 45,272
  • 113
  • 282
  • 475

18 Answers18

643
$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.

See Array Operators.

EDIT

The inequality operator is != while the non-identity operator is !== to match the equality operator == and the identity operator ===.

Stefan Gehrig
  • 80,936
  • 24
  • 154
  • 184
  • 98
    A side note: This approach **works** for multidimensional arrays as well (it wasn't that obvious for me before). – trejder Sep 23 '13 at 08:41
  • **Not works** when indexes not same... Example: my dump of {1,2,5} is `array(3) { [0]=>int(1) [1]=>int(2) [4]=>int(5) }` (indexes 0,1,4), but another arrays use indexes that are the expected (0,1,2). It is a PHP bug? – Peter Krauss Oct 13 '14 at 19:22
  • 5
    PS: solution is to use `array_values($a)==array_values($b)`... Another usual problem is about unique values, so remember that exist `array_unique()`. – Peter Krauss Oct 15 '14 at 10:53
  • 2
    Saying == checks for matching key/value pairs is a little misleading. It appears to actually check the values == each other. So you might be surprised to find that array(0) == array('not zero') is true. – Andrew Jul 31 '15 at 16:59
  • 53
    @nawfal: Your assumption is wrong. `['a', 'b']` is an array `[0 => 'a', 1 => 'b']`, while `['b', 'a']` is an array `[0 => 'b', 1 => 'a']`. That's why they don't have the same key/value pairs as stated in my answer and that's why `==` does not work between those. – Stefan Gehrig Nov 15 '15 at 13:00
  • 41
    @StefanGehrig oh you're right. I will leave my comment as such to make my foolishness evident :) – nawfal Nov 15 '15 at 13:03
  • 1
    +1 for `same order`. And it works with `===` even if keys in one array are numeric bounded by quotes. (e.g. '0', '1'). – shyammakwana.me May 04 '16 at 14:11
  • 1
    Note that `===` only requires values to have the same types and doesn't require keys, which means `([0 => 'a', 1 => 'b'] === [false => 'a', '1' => 'b']) === true`. – samluthebrave Jan 22 '17 at 02:02
  • 1
    http://stackoverflow.com/questions/21138505/check-if-two-arrays-have-the-same-values is the best way – Aaska Patel Feb 21 '17 at 10:32
  • 1
    can anyone link to an explanation as to why === is faster in large arrays than == (100k character arrays) – HaydenKai Jun 06 '17 at 05:45
  • 1
    [1,2] === [2,1] returns false – holden321 Aug 14 '18 at 06:46
  • 1
    @holden321. That's because `[1,2] === [2,1]` *is* false. See Stefan Gehrig's explanation above. `[1, 2]` is shorthand notation for `[0 => 1, 1 => 2]`, while `[2, 1]` is short for `[0 => 2, 1 => 1]`, so the two arrays *are* different, as keys and values don't match. – TRiG Oct 22 '19 at 09:44
  • 1
    Note that if you are importing CSV for example or from text files, this will probably do not work. Doing a var_dump you can notice that depending on the encoding of the file, an id that is supposely string(2) will come as string(5) so this comparation will fail. Even != will fail even with the claim that does not check types (at least does for me) – Martin Fasani Feb 14 '20 at 09:36
  • 1
    @WOUNDEDStevenJones somebody already removed. – nawfal Sep 23 '21 at 09:09
110

According to this page.

NOTE: The accepted answer works for associative arrays, but it will not work as expected with indexed arrays (explained below). If you want to compare either of them, then use this solution. Also, this function may not works with multidimensional arrays (due to the nature of array_diff function).

Testing two indexed arrays, which elements are in different order, using $a == $b or $a === $b fails, for example:

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

That is because the above means:

array(0 => "x", 1 => "y") vs. array(0 => "y", 1 => "x").

To solve that issue, use:

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

Comparing array sizes was added (suggested by super_ton) as it may improve speed.

Ivan
  • 24,563
  • 6
  • 44
  • 76
lepe
  • 23,582
  • 9
  • 92
  • 102
  • 3
    Attention: does not work as expected with [multidimensional arrays](http://stackoverflow.com/questions/19830585/why-array-diff-gives-array-to-string-conversion-error) – maersu Apr 09 '14 at 16:13
  • 10
    The above comment is false. If $b has all the elements $a has plus some extra ones, the two arrays are not equal yet the above code will say they are. – Ghola Sep 08 '14 at 12:14
  • 3
    might be worth adding count($a) == count($b) too – stefan Sep 07 '16 at 10:20
  • 2
    @super_ton: yes, before calling `array_diff` could speed-up the comparison. I will add it. Thanks – lepe Sep 08 '16 at 00:35
  • 1
    since **count($a) == count($b)**, another speed up is: `function array_equal($a, $b) { return ( is_array($a) && is_array($b) && count($a) == count($b) && !array_diff($a, $b) ); }` – Luca Manzo May 12 '17 at 07:57
  • 7
    Unfortunately, it does not work in some cases, for example, I've tested with the following case `$a = [1, 2, 2]; $b = [2, 1, 1];` and it returned `true`, but the two arrays are obviously not the same. – AwesomeGuy Sep 28 '18 at 13:00
  • if $a and $b have the same elements, both array_diff(a,b) and array_diff(b,a) are empty, the comparison between them doesn't make sense. – Pablo Pazos Oct 20 '20 at 21:48
40

Try serialize. This will check nested subarrays as well.

$foo =serialize($array_foo);
$bar =serialize($array_bar);
if ($foo == $bar) echo "Foo and bar are equal";
Iggi
  • 409
  • 4
  • 2
  • 9
    Problematic if the keys and values are shifted around just like using comparison. However, assuming they are expected to be 100% the same, this is the cleanest and easiest way to check deep equality! – Kevin Peno Aug 21 '13 at 20:59
  • 2
    I guess this is the best solution! It can compare multidimensional and associative arrays if they were previously sorted! – Rafael Moni Jul 24 '14 at 14:41
  • if the array is considered a SET, this doesn't work: it should be sorted on all nested levels to be able to check if the same items are included in any order. – Pablo Pazos Oct 20 '20 at 22:21
31

Short solution that works even with arrays which keys are given in different order:

public static function arrays_are_equal($array1, $array2)
{
    array_multisort($array1);
    array_multisort($array2);
    return ( serialize($array1) === serialize($array2) );
}
Samuel Vicent
  • 901
  • 9
  • 15
  • 7
    Probably the best answer so far, most of the answers either don't match if the keys are shifted or if it's a multidimensional array. – AwesomeGuy Sep 28 '18 at 13:06
  • Good choice! But note, that this method uses strict types comparsion, so if you want to compare [1,2,3] and ['1','2','3'] result would be false. – ChronoExp Jun 25 '20 at 20:02
  • Note that this won't work with numerically indexed arrays where you care about the index value. [array_multisort()](https://www.php.net/manual/en/function.array-multisort.php) which will re-index numeric keys. – Costa May 25 '22 at 05:38
13

Compare them as other values:

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

You can read about all array operators here: http://php.net/manual/en/language.operators.array.php Note for example that === also checks that the types and order of the elements in the arrays are the same.

Emil Vikström
  • 87,715
  • 15
  • 134
  • 170
12
function compareIsEqualArray(array $array1,array $array2):bool
{

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

}
Kris Erickson
  • 32,972
  • 26
  • 117
  • 173
dılo sürücü
  • 2,921
  • 1
  • 15
  • 24
9

!=== will not work because it's a syntax error. The correct way is !== (not three "equal to" symbols)

Thom Smith
  • 13,599
  • 6
  • 43
  • 83
Sodhi saab
  • 2,509
  • 2
  • 17
  • 32
8
if (array_diff($a,$b) == array_diff($b,$a)) {
  // Equals
}

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

From my pov it's better to use array_diff than array_intersect because with checks of this nature the differences returned commonly are less than the similarities, this way the bool conversion is less memory hungry.

Edit Note that this solution is for plain arrays and complements the == and === one posted above that is only valid for dictionaries.

4

Another method for checking equality regardless of value order works by using http://php.net/manual/en/function.array-intersect.php, like so:

$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';
}

Here's a version that works also with multidimensional arrays using 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;
}
whitebrow
  • 1,807
  • 18
  • 21
2

One way: (implementing 'considered equal' for https://www.rfc-editor.org/rfc/rfc6902#section-4.6)

This way allows associative arrays whose members are ordered differently - e.g. they'd be considered equal in every language but 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 https://www.rfc-editor.org/rfc/rfc6902#section-4.6
function considered_equal($a1, $a2) {
  return json_encode(rksort($a1)) === json_encode(rksort($a2));
}
Community
  • 1
  • 1
Mike McCabe
  • 995
  • 8
  • 9
2

Syntax problem on your arrays

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

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

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

var_dump($diff); 
Syscall
  • 18,131
  • 10
  • 32
  • 49
2

array_diff — Computes the difference of arrays

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

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

Compares array1 against one or more other arrays and returns the values in array1 that are not present in any of the other arrays.

Community
  • 1
  • 1
Scherbius.com
  • 3,368
  • 4
  • 22
  • 44
  • 10
    The OP wants to "check if two arrays are equal". `array_diff` can't tell you that. Try `array_diff([1, 2], [1, 2, 'hello'])`. – marcv Dec 02 '16 at 18:44
2

Here is the example how to compare to arrays and get what is different between them.

$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));

Result:

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

        )

    [b] => MISSING IN SECOND
    [1] => DIFFERENT
    [2] => MISSING IN FIRST
)
Marko Šutija
  • 345
  • 3
  • 9
0

If you want to check non associative arrays, here is the solution:

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

(count(array_unique(array_merge($a, $b))) === count($a)) ? 'Equals' : 'Not Equals';
// Equals
Santo Boldizar
  • 1,055
  • 13
  • 15
  • 1
    i got 'Equals' for the following: `$a = array('a', 'b', 'c', 'd');` `$b = array('a', 'c', 'b');` `echo (count(array_unique(array_merge($a, $b))) === count($a)) ? 'Equals' : 'Not Equals';` – backbone Jul 23 '20 at 12:19
0

The following solution works with custom equality functions that you can pass as a callback. Note that it doesn't check arrays order.

trait AssertTrait
{
    /**
     * Determine if two arrays have the same elements, possibly in different orders. Elements comparison function must be passed as argument.
     *
     * @param array<mixed> $expected
     * @param array<mixed> $actual
     *
     * @throws InvalidArgumentException
     */
    public static function assertArraysContainSameElements(array $expected, array $actual, callable $comparisonFunction): void
    {
        Assert::assertEquals(\count($expected), \count($actual));

        self::assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes($expected, $actual, $comparisonFunction);
        self::assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes($actual, $expected, $comparisonFunction);
    }

    /**
     * @param array<mixed> $needles
     * @param array<mixed> $haystack
     *
     * @throws InvalidArgumentException
     */
    private static function assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes(
        array $needles,
        array $haystack,
        callable $comparisonFunction
    ): void {
        Assert::assertLessThanOrEqual(\count($needles), \count($haystack));

        foreach ($needles as $expectedElement) {
            $matchesOfExpectedElementInExpected = \array_filter(
                $needles,
                static fn($element): bool => $comparisonFunction($expectedElement, $element),
            );

            $matchesOfExpectedElementInActual = \array_filter(
                $haystack,
                static fn($element): bool => $comparisonFunction($expectedElement, $element),
            );

            Assert::assertEquals(\count($matchesOfExpectedElementInExpected), \count($matchesOfExpectedElementInActual));
        }
    }
}

I usually use it in database integrations tests when I want to ensure that the expected elements are returned but I don't care about the sorting.

0

The proper way to compare whether two arrays are equal is to use strict equality (===), which compares recursively. Existing answers are unable to recursively sort an arbitrary array (array of arbitrary depth and order, containing a mixture of sequential and associative arrays) and hence cannot handle comparisons of arbitrary arrays. Sequential arrays are associative arrays with a sequential key (0,1,2,3...) whereas associative arrays do not have a sequential key.

To sort these arbitrary arrays, we have to:

  1. Traverse downwards towards leaf nodes with no more sub-arrays
  2. Sort sequential arrays by serializing then sorting them (to remove the need of having to use custom comparators)
  3. Sort associative arrays by key

The following code implements the solution described above. Improvements to the code are welcome.

function recur_sort( &$array ) {
    foreach ( $array as &$value ) {
       if ( is_array( $value ) ) recur_sort( $value );
    }

    if ( is_sequential_array( $array ) ) {
        $array = array_map( function( $el ) { return json_encode( $el ); }, $array  );
        sort( $array, SORT_STRING );
        $array = array_map( function( $el ) { return json_decode( $el, true ); }, $array  );
        return;
    } else {
        return ksort( $array );
    }
}

function is_sequential_array(Array &$a) {
    $n = count($a);
    for($i=0; $i<$n; $i++) {
        if(!array_key_exists($i, $a)) {
            return false;
        }
    }
    return true;
}

Example (in PHPUnit):

//A stricter and recursive assertEqualsCanonicalizing
public function assertSameCanonicalizing( $expected, $actual ) {
    recur_sort( $expected );
    recur_sort( $actual );
    $this->assertSame( $expected, $actual );
}
Toh Nic
  • 21
  • 2
0

If you want to check that your arrays have the strictly equal (===) associations of keys and values, you can use the following function:

function array_eq($a, $b) {
    // If the objects are not arrays or differ in their size, they cannot be equal
    if (!is_array($a) || !is_array($b) || count($a) !== count($b)) {
        return false;
    }
    // If the arrays of keys are not strictly equal (after sorting),
    // the original arrays are not strictly equal either
    $a_keys = array_keys($a);
    $b_keys = array_keys($b);
    array_multisort($a_keys);
    array_multisort($b_keys);
    if ($a_keys !== $b_keys) {
        return false;
    }
    // Comparing values
    foreach ($a_keys as $key) {
        $a_value = $a[$key];
        $b_value = $b[$key];
        // Either the objects are strictly equal or they are arrays
        // which are equal according to our definition. Otherwise they
        // are different.
        if ($a_value !== $b_value && !array_eq($a_value, $b_value)) {
            return false;
        }
    }
    return true;
}
Richard Blažek
  • 144
  • 1
  • 12
-1

Use php function array_diff(array1, array2);

It will return a the difference between arrays. If its empty then they're equal.

example:

$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' ) 

Example 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; 
Wolfgang Leon
  • 607
  • 9
  • 20
  • 2
    Technically, it does not return the difference between arrays. The documentation states "Compares array1 against one or more other arrays and returns the values in array1 that are not present in any of the other arrays.". So, if all the values from array1 are present in array2, even if array2 has more values, array_diff will return an empty array – 2pha Jun 13 '16 at 07:04
  • Does not "print null", prints an empty array (after fixing about a dozen syntax errors). Maybe you could use `(count(array_diff($a1, $a2)) + count(array_diff($a2, $a1))) === 0` to test if arrays are "equal" – user9645 Feb 03 '17 at 14:42
  • I fixed the syntax ( not null is empty, and I was mixing commas -.- ). What you're proposing I think is too much. Checking if its an empty array should be enough. – Wolfgang Leon Feb 03 '17 at 17:17