comparing arrays in php, without caring for the order

前端 未结 5 744
借酒劲吻你
借酒劲吻你 2020-12-10 03:42

I have two arrays, $a and $b here, and need to check if they contain exactly the same elements (independently of the order). I am thinking of using

if (sizeo         


        
相关标签:
5条回答
  • 2020-12-10 04:06

    If you think of the arrays as sets:

    Then your approach is almost correct (you need to drop the equality test for the element count).

    If it matters that the arrays contain multiple copies of the same element:

    Then your approach is not correct. You need to sort the arrays with sort and then compare them with ===. This should be faster, as it can abort the comparison the moment it sees one difference without going over the whole arrays.

    Update:

    Clarified exactly when the OP's approach would be correct or not, also incorporated the suggestion that sort would be probably better than asort here.

    0 讨论(0)
  • 2020-12-10 04:15

    The accepted answer is was wrong. It will would fail on: https://3v4l.org/U8U5p

    $a = ['x' => 1, 'y' => 2]; $b = ['x' => 1, 'y' => 1];

    Here is a correct solution:

    function consistsOfTheSameValues(array $a, array $b)
    {
        // check size of both arrays
        if (count($a) !== count($b)) {
            return false;
        }
    
        foreach ($b as $key => $bValue) {
    
            // check that expected value exists in the array
            if (!in_array($bValue, $a, true)) {
                return false;
            }
    
            // check that expected value occurs the same amount of times in both arrays
            if (count(array_keys($a, $bValue, true)) !== count(array_keys($b, $bValue, true))) {
                return false;
            }
    
        }
    
        return true;
    }
    

    Plus quite extensive unit tests: https://3v4l.org/m6lHv

    <?php
    
    // A unit testing framework in a tweet. https://gist.github.com/mathiasverraes/9046427
    function it($m,$p){echo ($p?'✔︎':'✘')." It $m\n"; if(!$p){$GLOBALS['f']=1;}}function done(){if(@$GLOBALS['f'])die(1);}
    
    function consistsOfTheSameValues(array $a, array $b)
    {
        // check size of both arrays
        if (count($a) !== count($b)) {
            return false;
        }
    
        foreach ($b as $key => $bValue) {
    
            // check that expected value exists in the array
            if (!in_array($bValue, $a, true)) {
                return false;
            }
    
            // check that expected value occurs the same amount of times in both arrays
            if (count(array_keys($a, $bValue, true)) !== count(array_keys($b, $bValue, true))) {
                return false;
            }
    
        }
    
        return true;
    }
    
    it('consist of the same values',
        consistsOfTheSameValues([1], [1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues([1, 1], [1, 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['1', 1], ['1', 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['1', 1], [1, '1']) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues([1, '1'], ['1', 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues([1, '1'], [1, '1']) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['x' => 1], ['x' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['x' => 1], ['y' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['y' => 1], ['x' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 1, 'y' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['y' => 1, 'x' => 1], ['x' => 1, 'y' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['x' => 1, 'y' => 1], ['y' => 1, 'x' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['y' => 1, 'x' => 1], ['y' => 1, 'x' => 1]) === true
    );
    
    it('consist of the same values',
        consistsOfTheSameValues(['x' => 2, 'y' => 1], ['x' => 1, 'y' => 2]) === true
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1], [2]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1'], [1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1], ['1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1], [1, 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, 1], [1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1', 1], [1, 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, '1'], [1, 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, 1], ['1', 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, 1], [1, '1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1', '1'], [1, 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1', '1'], ['1', 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1', '1'], [1, '1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, 1], ['1', '1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['1', 1], ['1', '1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues([1, '1'], ['1', '1']) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['x' => 1], ['x' => 2]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 1, 'y' => 2]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 2, 'y' => 1]) === false
    );
    
    it('does not consist of the same values',
        consistsOfTheSameValues(['x' => 2, 'y' => 1], ['x' => 1, 'y' => 1]) === false
    );
    

    @update:

    Extensive unit test of @ircmaxell answer: https://3v4l.org/5ivgm

    Extensive unit test of @Jon anwser: https://3v4l.org/CrTgQ

    0 讨论(0)
  • 2020-12-10 04:18

    The accepted answer fails to account for duplicates. Here is my take

    public function sameElements($a, $b)
    {
       sort($a);
       sort($b);
       return $a == $b;
    }
    
    0 讨论(0)
  • 2020-12-10 04:23

    Just for your amusement I'll add an example that demonstrates that your conditions is not correct:

    <?php
    $a = array(1, 1, 2);
    $b = array(1, 2, 3);
    
    var_dump(sizeof($a)==sizeof($b) AND array_diff($a,$b)==array());
    ?>
    

    Test it.

    I would suggest using a different model. Maybe adding the elements as keys of the array, but this is possible only if they are integers or strings.

    $arr['itemA'] = true;
    $arr['itemB'] = true;
    

    This will enforce uniqueness. With this model you can use your condition on array_keys($arr).

    0 讨论(0)
  • 2020-12-10 04:24

    Well, we can do something like this:

    if (count(array_diff(array_merge($a, $b), array_intersect($a, $b))) === 0) {
        //they are the same!
    }
    

    The reason it works, is that array_merge will make a big array that has all the elements of both $a and $b (all the elements that are in either $a, $b, or both). array_intersect will create an array that has all the elements that are in both $a and $b only. So if they are different,, there must be at least one element that does not appear in both arrays...

    Also note that sizeof is not an actual function/construct, it's an alias. I'd suggest using count() for clarity...

    0 讨论(0)
提交回复
热议问题