在php中比较数组,而不关心顺序

发布于 2024-10-08 22:38:57 字数 228 浏览 0 评论 0原文

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

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

}

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

由于我需要将它们用作集合,也许我根本不应该使用数组,而应该使用其他东西。

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 (sizeof($a)==sizeof($b) AND array_diff($a,$b)==array())
{

}

But I am new to PHP, so I wonder: Is there a better way?

Since I need to use them as sets, maybe I should not use arrays at all but something else.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一影成城 2024-10-15 22:38:57

好吧,我们可以做这样的事情:

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()...

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

信仰 2024-10-15 22:38:57

接受的答案无法解释重复项。这是我的看法

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

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

public function sameElements($a, $b)
{
   sort($a);
   sort($b);
   return $a == $b;
}
浅忆 2024-10-15 22:38:57

接受的答案是错误的。它将会会失败: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

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

爺獨霸怡葒院 2024-10-15 22:38:57

如果您将数组视为集合

那么您的方法几乎是正确的(您需要放弃元素计数的相等测试)。

如果数组包含同一元素的多个副本很重要:

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

更新:

准确地澄清了OP的方法何时正确或不正确,还在这里合并了sort可能比asort更好的建议。

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.

倾听心声的旋律 2024-10-15 22:38:57

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

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

var_dump(sizeof($a)==sizeof($b) AND array_diff($a,$b)==array());
?>

测试一下。

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

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

这将增强唯一性。使用此模型,您可以在 array_keys($arr) 上使用您的条件。

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

℡Ms空城旧梦 2024-10-15 22:38:57

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

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

A decade has passed since asked, but I stumbled upon kind of similar challenge and I want to share my own solution that also works for multi-dimensional array:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文