比较PHP中的数组,而不关心订单

时间:2010-12-23 14:56:58

标签: php arrays comparison set

我有两个数组,$ a和$ b,需要检查它们是否包含完全相同的元素(与顺序无关)。我正在考虑使用

if (sizeof($a)==sizeof($b) AND array_diff($a,$b)==array())
{

}

但我是PHP的新手,所以我想知道:有更好的方法吗?

因为我需要将它们用作集合,所以我可能根本不应该使用数组。

6 个答案:

答案 0 :(得分:12)

好吧,我们可以这样做:

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

它起作用的原因是,array_merge将构成一个包含$a$b所有元素的大数组($a中的所有元素},$b或两者兼而有之)。 array_intersect将创建一个数组,其中包含$a$b中的所有元素。因此,如果它们不同,则必须至少有一个元素不会出现在两个数组中......

另请注意sizeof不是实际的函数/构造,它是别名。为了清晰起见,我建议使用count()

答案 1 :(得分:6)

接受的答案是错误的!它会失败:https://3v4l.org/U8U5p

$a = ['x' => 1, 'y' => 2]; $b = ['x' => 1, 'y' => 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;
}

加上相当广泛的单元测试: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:

@ircmaxell的广泛单元测试答案:https://3v4l.org/5ivgm

@Jon anwser的广泛单元测试:https://3v4l.org/CrTgQ

答案 2 :(得分:3)

接受的答案没有说明重复。这是我的看法

public function sameElements($a, $b)
{
   sort($a);
   sort($b);
   return $a == $b;
}

答案 3 :(得分:2)

如果您将数组视为集合

然后您的方法几乎正确(您需要删除元素计数的相等测试)。

如果数组包含相同元素的多个副本

然后你的方法正确。您需要使用sort对数组进行排序,然后将它们与===进行比较。这应该更快,因为它可以在看到一个差异而不越过整个数组时中止比较。

<强>更新

明确说明OP的方法是否正确,还包含sort可能比asort更好的建议。

答案 4 :(得分:2)

为了您的娱乐,我将添加一个示例,证明您的条件不正确:

<?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.

我建议使用不同的型号。也许将元素添加为数组的键,但只有当它们是整数或字符串时才可能。

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

这将强制实现独特性。使用此模型,您可以在array_keys($arr)上使用您的条件。

答案 5 :(得分:0)

自问以来已经过去了十年,但我偶然发现了类似的挑战,我想分享我自己的解决方案,该解决方案也适用于多维数组:

public static function isSame($a, $b, bool $is_strict = true): bool
{
    // check PHP evaluation first
    if ($is_strict ? ($a === $b) : ($a == $b))
    {
        return true;
    }

    // comparing scalar is done above, now recursive array comparison
    if (!is_array($a) || !is_array($b))
    {
        return false;
    }

    foreach ([[$a, $b], [$b, $a]] as [$x, $y])
    {
        foreach ($x as $xkey => $xval)
        {
            if (!array_key_exists($xkey, $y))
            {
                return false;
            }
    
            if (!self::isSame($xval, $y[$xkey], $is_strict))
            {
                return false;
            }
        }
    }

    return true;
}