21

Is there a built-in function for PHP for me to check whether two arrays contain the same values ( order not important?).

For example, I want a function that returns me true for the following two inputs:

array('4','5','2') 
array('2','4','5')

Edit: I could have sorted the two arrays and compare them, but as I am such a lazy guy, I would still prefer a one-liner that I can pull out and use.

Graviton
  • 81,782
  • 146
  • 424
  • 602
  • How should the code handle situations where arrays have more than one instance of the same value, for example `array(1, 2, 3)` vs `array(1, 2, 3, 1)`? Some of the answers will return true, others false. Also, some will return inconsistent results due to short-circuiting via count(), and will return false in the first example but true if comparing `array(1, 2, 3, 1)` with `array(1, 2, 3, 2)`. My guess is that this doesn't apply in your situation, but for anyone looking for an answer where duplicate entries may exist, care must be taken to use an algorithm that meets your specific requirements. – HappyDog Jul 08 '19 at 13:08

8 Answers8

32

array_diff looks like an option:

function array_equal($a1, $a2) {
  return !array_diff($a1, $a2) && !array_diff($a2, $a1);
}

or as an oneliner in your code:

if(!array_diff($a1, $a2) && !array_diff($a2, $a1)) doSomething();
knittl
  • 246,190
  • 53
  • 318
  • 364
  • 3
    You can use `empty` only with varliables. – Gumbo Sep 10 '09 at 09:27
  • gumbo: no, you can use it on arrays just fine. taken from : “The following things are considered to be empty: # array() (an empty array)” – knittl Sep 10 '09 at 09:40
  • 3
    Gumbo is right. You can't use a function's return value with `empty`. That's what he was actually saying. You have to store the return value of `array_diff` in a temp variable or just use the not operator: `return !array_diff($a1, $a2)`. – Ionuț G. Stan Sep 10 '09 at 09:44
  • 1
    @knittl: No, you can only test variables and not values. *`empty()` only checks variables as anything else will result in a parse error.* Again, see http://docs.php.net/empty – Gumbo Sep 10 '09 at 09:44
  • ionut: ok, that makes more sense. i’ve just tried it, and you’re both correct. i edited my answer to use a boolean cast (negate) – knittl Sep 10 '09 at 09:47
  • A parse error or a `Fatal error: Can't use function return value in write context`. In knittl's case the fatal error will be issued. – Ionuț G. Stan Sep 10 '09 at 09:48
  • as mentioned below by Mike, you actually have to do `!array_diff($a1,$a2) && !array_diff($a2,$a1)` – Weboide Feb 12 '11 at 19:05
  • Slightly shorter: `array_diff($a1, $a2) == array_diff($a2, $a1)`. They would both be empty, and there's no way they could be equal in any other case :-) – jgivoni Sep 19 '13 at 11:12
  • You can have the sort way also as an inliner: `if(sort($a1) && sort($a2) && $a1 == $a2)`. Furthermore this approach was 10x as fast as the array_diff approach (at least on my machine with php5.5) – velop Apr 14 '14 at 17:25
9

The best solution is to sort both array and then compare them:

$a = array('4','5','2');
$b = array('2','4','5');
sort($a);
sort($b);
var_dump($a === $b);

As a function:

function array_equal($a, $b, $strict=false) {
    if (count($a) !== count($b)) {
        return false;
    }
    sort($a);
    sort($b);
    return ($strict && $a === $b) || $a == $b;
}

Here’s another algorithm looking for each element of A if it’s in B:

function array_equal($a, $b, $strict=false) {
    if (count($a) !== count($b)) {
        return false;
    }
    foreach ($a as $val) {
        $key = array_search($val, $b, $strict);
        if ($key === false) {
            return false;
        }
        unset($b[$key]);
    }
    return true;
}

But that has a complexity of O(n^2). So you better use the sorting method.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • as I am such a lazy guy, I would still prefer a one-liner that I can pull out and use. – Graviton Sep 10 '09 at 08:45
  • 2
    @Ngu Soon Hui - so wrap Gumbo's code into a function (array_equals($arr1,$arr2))? – karim79 Sep 10 '09 at 08:47
  • 2
    It would be helpful if the down-voter commented on why he voted my answer down. – Gumbo Sep 10 '09 at 10:10
  • @Gumbo Maybe, because he or she is a sick prick (sorry! :~), and that's why he or she downvoted a perfectly valid and professionally written answer? :] – trejder Sep 23 '13 at 07:36
3

The array_diff() method above won't work.

php.net's manual says that array_diff() does this:

"Returns an array containing all the entries from array1 that are not present in any of the other arrays."

So the actual array_diff() method would be:

function array_equal($array1, $array2)
{
   $diff1 = array_diff($array1, $array2);
   $diff2 = array_diff($array2, $array1);

   return
   (
      (count($diff1) === 0) &&
      (count($diff2) === 0)
   );
}

However I go with the sort method :D

Mike
  • 171
  • 1
  • 2
  • +1 that's a better way to do it. I found that issue today and ended up using `!array_diff($a,$b) && !array_diff($b,$a)`. Not the best solution, but it does work. – Weboide Feb 12 '11 at 19:02
  • A side note: Though, this is out of OP's question, it is worth to remember, that using `array_diff()` (and similar like `array_intersect()`) will **fail on multidimensional arrays** (PHP notice: _Array to string conversion_), while using simple array operators of `==` and `===` will work on such arrays without any problems. – trejder Sep 23 '13 at 08:47
1

You can use array_diff.

$a = array('4','5','2');
$b = array('2','4','5');

if(count(array_diff($a, $b)) == 0) {
  // arrays contain the same elements
} else {
  // arrays contain different elements
}

However, a problem with this approach is that arrays can contain duplicate elements, and still match.

Alistair Evans
  • 36,057
  • 7
  • 42
  • 54
0

You only need to compare one-way using array_diff() and use count() for the inverted relationship.

if (count($a1) == count($a2) && !array_diff($a1, $a2)) {
    // equal arrays
}
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
Dror Dromi
  • 157
  • 1
  • 4
  • Down-voting as a general solution, as this will only work if both arrays are unique. It will not give the correct result if either array contains more than one instance of the same value. – HappyDog Jul 08 '19 at 13:00
0

If the arrays being compared consist of only strings and/or integers, array_count_values allows you to compare the arrays quickly (in O(n) time vs O(n log n) for sorting) by verifying that both arrays contain the same values and that each value occurs the same # of times in both arrays.

if(array_count_values($a1) == array_count_values($a2)) {
    //arrays are equal
}
FuzzyTree
  • 32,014
  • 3
  • 54
  • 85
0

As an addition to the accepted reply from @knittl

To cover the case, when one of the arrays has additional members:

function areEqualIfOrderIgnored(array $a1, array $a2): bool
{
    if (
        ! array_diff($a1, $a2)
        && ! array_diff($a2, $a1)
        && count($a1) === count($a2)
    ) {
        return true;
    }

    return false;
}

Or one line, as requested (but not nice)

if (! array_diff($a1, $a2) && ! array_diff($a2, $a1) && count($a1) === count($a2)) {do smth}
0

You can use array_intersect() instead of array_diff():

$a = array('4','5','2');
$b = array('2','4','5');
$ca = count($a);
$cb = count($b);
$array_equal = ( $ca == $cb && $ca == count(array_intersect($a, $b)) );

Performance wise. solution, where two factors are important:

  • the more often arrays are matching, the more array_intersect() is fast.
  • the more arrays are big (more than 10 values), the more array_intersect() is fast.

Depending on these factors, one method can be two or three time faster than the other. For big arrays with few (or no) matching combinations, or for little arrays with lots of matching, both methods are equivalent.

However, the sort method is always faster, except in the case with little arrays with few or no matching combinations. In this case the array_diff() method is 30% faster.

trejder
  • 17,148
  • 27
  • 124
  • 216
roselan
  • 3,755
  • 1
  • 20
  • 20
  • Formatting notice: You used poorly written HTML instead of Markdown (fixed) and you seems to be not liking capital letters in the beginning of each section (fixed). So in general, I should downvote your laziness! :] But, on the other hand, you provided an exceptional and interesting answer, so that's fine! :] – trejder Sep 23 '13 at 07:40