检查两个数组是否具有相同的值(无论值顺序如何)

发布于 2025-01-18 11:56:32 字数 164 浏览 0 评论 0原文

[2,5,3]    

[5,2,3]

它们是相等的,因为它们具有相同的值,但顺序不同。

我可以在不使用 foreach() 循环和 in_array() 的情况下找到答案吗?我认为这不会有效率。

[2,5,3]    

[5,2,3]

They are equal because they have the same values, but not in the same order.

Can I find that out without using a foreach() loop with in_array()? I don't think it would be efficient.

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

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

发布评论

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

评论(12

踏月而来 2025-01-25 11:56:32
sort($a);
sort($b);
if ($a===$b) {//equal}
sort($a);
sort($b);
if ($a===$b) {//equal}
往事随风而去 2025-01-25 11:56:32

迟到了这个聚会。我也有同样的问题,但不想分类,这是我知道会起作用的直接答案。我想出了这个简单的单线,它仅适用于独特值的数组

$same = ( count( $a ) == count( $b ) && !array_diff( $a, $b ) )

它也比排序选项快约5倍。并不是要这两个都特别慢,所以我想说的更多是关于您的个人偏好,以及您认为更清楚的一种。就我个人而言,我宁愿不排序。

编辑:感谢Ray指出的事实,即这仅适用于具有唯一值的数组。

Coming to this party late. I had the same question but didn't want to sort, which was the immediate answer I knew would work. I came up with this simple one-liner which only works for arrays of unique values:

$same = ( count( $a ) == count( $b ) && !array_diff( $a, $b ) )

It's also about a factor of 5 faster than the sort option. Not that either is especially slow, so I would say it is more about your personal preferences and which one you think is more clear. Personally I would rather not sort.

Edit: Thanks Ray for pointing out the fact that this only works with arrays with unique values.

欢烬 2025-01-25 11:56:32

这对聚会有点晚,但希望它将有用:

如果您确定阵列都只包含字符串或仅包含整数,则array_count_values($ a)== array_count_values($ b)< /代码>具有更好的时间复杂性。但是,User1844933的答案更为笼统。

This is a bit late to the party but in hopes that it will be useful:

If you are sure the arrays both only contain strings or both only contain integers, then array_count_values($a) == array_count_values($b) has better time complexity. However, user1844933's answer is more general.

信仰 2025-01-25 11:56:32

如果您不想对数组进行排序,而只想检查相等性而不管值顺序如何,请使用 http://php.net/manual/en/function.array-intersect.php 像这样:

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

If you don't want to sort arrays but just want to check equality regardless of value order use 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';
}
眼泪淡了忧伤 2025-01-25 11:56:32

最好的方法是使用array_diff http:http:http:http:// php php .net/manual/en/function.array-diff.php

$arr1 = [2,5,3];
$arr2 = [5,2,3];

$isEqual = array_diff($arr1,$arr2) === array_diff($arr2,$arr1);

The best way will be using array_diff http://php.net/manual/en/function.array-diff.php

$arr1 = [2,5,3];
$arr2 = [5,2,3];

$isEqual = array_diff($arr1,$arr2) === array_diff($arr2,$arr1);
时光匆匆的小流年 2025-01-25 11:56:32

由于给定的答案中没有一个完全独立于键的工作与重复的值(例如 [1,1,2] 等于 [1,2,2]),我'我自己写的。

此变体不适用于多维数组。它确实检查两个数组是否包含完全相同的值,无论它们的键和顺序如何,而不修改任何参数。

function array_equals(array $either, array $other) : bool {
    foreach ($other as $element) {
        $key = array_search($element, $either, true);
        if ($key === false) {
            return false;
        }
        unset($either[$key]);
    }
    return empty($either);
}

尽管问题询问的是无 foreach 变体,但我找不到任何无需循环即可满足我的要求的解决方案。此外,大多数其他使用的函数也在内部使用循环。


为什么它不修改$either?因为 PHP 中的值是写时复制的,所以只要这是它自己的函数而不是内联代码,一旦 $either 参数被修改,数组就会被复制第一次。

如果您想内联此代码,请先执行此操作:

$either = $myarray;
// inline code from function above

As none of the given answers that are completely key-independent work with duplicated values (like [1,1,2] equals [1,2,2]) I've written my own.

This variant does not work with multi-dimensional arrays. It does check whether two arrays contain the exactly same values, regardless of their keys and order without modifying any of the arguments.

function array_equals(array $either, array $other) : bool {
    foreach ($other as $element) {
        $key = array_search($element, $either, true);
        if ($key === false) {
            return false;
        }
        unset($either[$key]);
    }
    return empty($either);
}

Although the question asked about a foreach-free variant, I couldn't find any solution that satisfied my requirements without a loop. Additionally most of the otherwise used functions use a loop internally too.


Why does it not modify $either? Because values in PHP are copy-on-write, so as long as this is its own function and not inline code the array is copied once the $either argument is modified for the first time.

If you want to inline this code do this before:

$either = $myarray;
// inline code from function above
月亮是我掰弯的 2025-01-25 11:56:32

如何将数组转换为字符串,然后比较字符串。

sort($a);
sort($b);
$a_str = implode(",", $a);
$b_str = implode(",", $b);
f ( strcmp($a_str, $b_str) !== 0)
{
}

How about converting the arrays to strings and then comparing the strings.

sort($a);
sort($b);
$a_str = implode(",", $a);
$b_str = implode(",", $b);
f ( strcmp($a_str, $b_str) !== 0)
{
}
も让我眼熟你 2025-01-25 11:56:32

比方说,如果你有两个这样定义的数组:

$array1 = array(2,5,3);
$array2 = array(5,2,3);

那么你可以用这段代码来判断它们是否相等:

if(array_diff($array1,$array2) === array_diff($array2,$array1) &&count($array1)==count($array2))
{
    echo 'Equal';
}
else
{
    echo 'Not equal';
}

Say, if you have two arrays defined like this:

$array1 = array(2,5,3);
$array2 = array(5,2,3);

Then you can use this piece of code to judge whether they equal:

if(array_diff($array1,$array2) === array_diff($array2,$array1) &&count($array1)==count($array2))
{
    echo 'Equal';
}
else
{
    echo 'Not equal';
}
冧九 2025-01-25 11:56:32
function array_equal($a, $b){
return count($a) === count($b) && empty(array_diff($a, $b)) && empty(array_diff($b, $a));
}

这是准确的解决方案

function array_equal($a, $b){
return count($a) === count($b) && empty(array_diff($a, $b)) && empty(array_diff($b, $a));
}

Here is the accurate solution

北座城市 2025-01-25 11:56:32

给定的答案包含各种怪癖,这些怪癖证明这不是一个简单的问题,并且定义“相同值”对您的域而言意味着什么很重要。我的解决方案需要以下设计目标:

  • 两个阵列都应被视为“列表”。
  • 该解决方案应与包含所有类型的数组(包括对象,与枚举之类的功能兼容)。
  • 应支持重复的元素。
  • 不起作用的情况应引发例外。

评估解决方案的测试案例看起来像:

<?php

namespace App\Tests\Unit\Utility;

use App\Utility\ArrayUtil;
use PHPUnit\Framework\TestCase;

class ArrayUtilTest extends TestCase {

    /**
     * @dataProvider elementsEqualDataProviderTrueCases
     */
    public function test_elements_are_equal_true_cases(array $array1, array $array2): void {
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertTrue(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    /**
     * @dataProvider elementsEqualDataProviderFalseCases
     */
    public function test_elements_are_equal_false_cases(array $array1, array $array2): void {
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertFalse(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    /**
     * @dataProvider exceptionTestCases
     */
    public function test_elements_are_equal_exceptional_cases(mixed $array1, mixed $array2, string $exception): void {
        $this->expectException($exception);
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertFalse(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    public function elementsEqualDataProviderTrueCases(): \Generator {
        yield 'Empty arrays' => [
            [],
            [],
        ];
        yield 'Integer types' => [
            [1, 2, 3],
            [3, 2, 1],
        ];
        yield 'Boolean types' => [
            [true, false],
            [false, true],
        ];
        yield 'String types' => [
            ["abc", "def"],
            ["def", "abc"],
        ];
        $objectA = new \stdClass();
        $objectB = new \stdClass();
        yield 'Object types' => [
            [$objectA, $objectB],
            [$objectB, $objectA],
        ];

        $objectC = new \stdClass();
        yield 'Mixed types' => [
            [2, true, "foo", null, $objectC],
            ["foo", null, 2, true, $objectC],
        ];
        yield 'Array types' => [
            [[1, 2], [3, 4]],
            [[3, 4], [1, 2]],
        ];
        yield 'Repeated values' => [
            [1, 1, 2],
            [2, 1, 1],
        ];
    }

    public function elementsEqualDataProviderFalseCases(): \Generator {
        yield 'Integer types' => [
            [1, 2, 3],
            [4, 5, 6],
        ];
        yield 'Boolean types' => [
            [true],
            [false],
        ];
        yield 'String types' => [
            ["abc", "def"],
            ["hij", "abc"],
        ];
        yield 'Object types' => [
            [new \stdClass(), new \stdClass()],
            [new \stdClass(), new \stdClass()],
        ];
        $objectC = new \stdClass();
        yield 'Mixed types' => [
            [2, false, "foo", null, $objectC],
            ["foo", null, 2, true, $objectC],
        ];
        yield 'Array types' => [
            [[1, 2], [3, 4]],
            [[4, 3], [2, 1]],
        ];
        yield 'Repeated values' => [
            [1, 1, 2],
            [2, 2, 1],
        ];
        yield 'Repeated values, longer second argument' => [
            [1, 1, 2],
            [2, 2, 1, 1],
        ];
        yield 'Repeated values, longer first argument' => [
            [1, 1, 2, 2],
            [2, 2, 1],
        ];
    }

    public function exceptionTestCases(): \Generator {
        yield 'Non-list array first argument' => [
            ['foo' => 'bar'],
            [1, 2, 3],
            \InvalidArgumentException::class,
        ];
        yield 'Non-list array second argument' => [
            [1, 2, 3],
            ['foo' => 'bar'],
            \InvalidArgumentException::class,
        ];
        yield 'Non array arguments' => [
            "foo",
            "bar",
            \TypeError::class,
        ];
    }
}

解决方案(主要是根据Seyfahni的答案进行的):

<?php

namespace App\Utility;

final class ArrayUtil {
    public static function elementsEqual(array $array1, array $array2): bool {
        if (!array_is_list($array1) || !array_is_list($array2)) {
            throw new \InvalidArgumentException('Arrays compared for element equality must both be lists.');
        }
        if (count($array1) !== count($array2)) {
            return false;
        }
        foreach ($array1 as $element) {
            $key = array_search($element, $array2, true);
            if ($key === false) {
                return false;
            }
            unset($array2[$key]);
        }
        return empty($array2);
    }
}

The given answers contain various quirks that prove this is not a straightforward problem and defining what "same values" means up-front for your domain is important. My solution for this required the following design goals:

  • Both arrays should be considered "lists".
  • The solution should work with arrays that contain all types (including objects, for compatibility with features like enums).
  • Repeated elements should be supported.
  • Cases that don't work should throw exceptions.

The test case to evaluate solutions looks like:

<?php

namespace App\Tests\Unit\Utility;

use App\Utility\ArrayUtil;
use PHPUnit\Framework\TestCase;

class ArrayUtilTest extends TestCase {

    /**
     * @dataProvider elementsEqualDataProviderTrueCases
     */
    public function test_elements_are_equal_true_cases(array $array1, array $array2): void {
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertTrue(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    /**
     * @dataProvider elementsEqualDataProviderFalseCases
     */
    public function test_elements_are_equal_false_cases(array $array1, array $array2): void {
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertFalse(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    /**
     * @dataProvider exceptionTestCases
     */
    public function test_elements_are_equal_exceptional_cases(mixed $array1, mixed $array2, string $exception): void {
        $this->expectException($exception);
        $originalArray1 = serialize($array1);
        $originalArray2 = serialize($array2);
        $this->assertFalse(ArrayUtil::elementsEqual($array1, $array2));
        $this->assertSame($originalArray1, serialize($array1));
        $this->assertSame($originalArray2, serialize($array2));
    }

    public function elementsEqualDataProviderTrueCases(): \Generator {
        yield 'Empty arrays' => [
            [],
            [],
        ];
        yield 'Integer types' => [
            [1, 2, 3],
            [3, 2, 1],
        ];
        yield 'Boolean types' => [
            [true, false],
            [false, true],
        ];
        yield 'String types' => [
            ["abc", "def"],
            ["def", "abc"],
        ];
        $objectA = new \stdClass();
        $objectB = new \stdClass();
        yield 'Object types' => [
            [$objectA, $objectB],
            [$objectB, $objectA],
        ];

        $objectC = new \stdClass();
        yield 'Mixed types' => [
            [2, true, "foo", null, $objectC],
            ["foo", null, 2, true, $objectC],
        ];
        yield 'Array types' => [
            [[1, 2], [3, 4]],
            [[3, 4], [1, 2]],
        ];
        yield 'Repeated values' => [
            [1, 1, 2],
            [2, 1, 1],
        ];
    }

    public function elementsEqualDataProviderFalseCases(): \Generator {
        yield 'Integer types' => [
            [1, 2, 3],
            [4, 5, 6],
        ];
        yield 'Boolean types' => [
            [true],
            [false],
        ];
        yield 'String types' => [
            ["abc", "def"],
            ["hij", "abc"],
        ];
        yield 'Object types' => [
            [new \stdClass(), new \stdClass()],
            [new \stdClass(), new \stdClass()],
        ];
        $objectC = new \stdClass();
        yield 'Mixed types' => [
            [2, false, "foo", null, $objectC],
            ["foo", null, 2, true, $objectC],
        ];
        yield 'Array types' => [
            [[1, 2], [3, 4]],
            [[4, 3], [2, 1]],
        ];
        yield 'Repeated values' => [
            [1, 1, 2],
            [2, 2, 1],
        ];
        yield 'Repeated values, longer second argument' => [
            [1, 1, 2],
            [2, 2, 1, 1],
        ];
        yield 'Repeated values, longer first argument' => [
            [1, 1, 2, 2],
            [2, 2, 1],
        ];
    }

    public function exceptionTestCases(): \Generator {
        yield 'Non-list array first argument' => [
            ['foo' => 'bar'],
            [1, 2, 3],
            \InvalidArgumentException::class,
        ];
        yield 'Non-list array second argument' => [
            [1, 2, 3],
            ['foo' => 'bar'],
            \InvalidArgumentException::class,
        ];
        yield 'Non array arguments' => [
            "foo",
            "bar",
            \TypeError::class,
        ];
    }
}

And the solution (adapted primarily from seyfahni's answer):

<?php

namespace App\Utility;

final class ArrayUtil {
    public static function elementsEqual(array $array1, array $array2): bool {
        if (!array_is_list($array1) || !array_is_list($array2)) {
            throw new \InvalidArgumentException('Arrays compared for element equality must both be lists.');
        }
        if (count($array1) !== count($array2)) {
            return false;
        }
        foreach ($array1 as $element) {
            $key = array_search($element, $array2, true);
            if ($key === false) {
                return false;
            }
            unset($array2[$key]);
        }
        return empty($array2);
    }
}
戴着白色围巾的女孩 2025-01-25 11:56:32

我已经检查了这里的所有答案,并为大多数(如果不是全部)测试用例提出了统一的解决方案:

解决方案:

if (!function_exists("array_same")) {
    function array_same(array $first, array $second): bool
    {
        return array_count_values(
                array_map("serialize", $first)
            )
            == array_count_values(
                array_map("serialize", $second)
            );
    }
}

测试用例:


$print = fn(array $a, array $b, string $answer) => json_encode($a)
    . " === "
    . json_encode($b)
    . " = "
    . $answer;

$a = ['red', 'red', 'blue', 'blue'];
$b = ['red', 'blue', 'red', 'blue'];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = ['red', 'red', 'blue', 'blue'];
$b = ['red', 'red', 'red', 'blue'];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = ['a'];
$b = [true];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = [true];
$b = [1];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = [41.235, 'a', 41, 'a', 'b', true];
$b = ['a', 41.235, 'b', true, 'a', 41];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = [new \stdClass()];
$b = [new \stdClass()];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = [null];
$b = [false];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

I have inspected all the answers here and came up with a uniform solution for most if not all test cases:

Solution:

if (!function_exists("array_same")) {
    function array_same(array $first, array $second): bool
    {
        return array_count_values(
                array_map("serialize", $first)
            )
            == array_count_values(
                array_map("serialize", $second)
            );
    }
}

Test Cases:


$print = fn(array $a, array $b, string $answer) => json_encode($a)
    . " === "
    . json_encode($b)
    . " = "
    . $answer;

$a = ['red', 'red', 'blue', 'blue'];
$b = ['red', 'blue', 'red', 'blue'];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = ['red', 'red', 'blue', 'blue'];
$b = ['red', 'red', 'red', 'blue'];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = ['a'];
$b = [true];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = [true];
$b = [1];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".

echo PHP_EOL;

$a = [41.235, 'a', 41, 'a', 'b', true];
$b = ['a', 41.235, 'b', true, 'a', 41];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = [new \stdClass()];
$b = [new \stdClass()];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "true".

echo PHP_EOL;

$a = [null];
$b = [false];
echo array_same($a, $b)
    ? $print($a, $b, 'true')
    : $print($a, $b, 'false'); // "false".
蓝色星空 2025-01-25 11:56:32
$array1 = array(2,5,3);
$array2 = array(5,2,3);
$result = array_diff($array1, $array2);
if(empty($result))
{
   echo "Both arrays are equal.";
}
else
{
   echo "Both arrays are different.";
}
$array1 = array(2,5,3);
$array2 = array(5,2,3);
$result = array_diff($array1, $array2);
if(empty($result))
{
   echo "Both arrays are equal.";
}
else
{
   echo "Both arrays are different.";
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文