我想检查两个数组是否相等。我的意思是:相同的大小,相同的索引,相同的值。我该怎么做呢?
根据用户的建议使用!==,如果数组中至少有一个元素是不同的,我希望下面的代码会打印enter,但实际上并不是这样。
if (($_POST['atlOriginal'] !== $oldAtlPosition)
or ($_POST['atl'] !== $aext)
or ($_POST['sidesOriginal'] !== $oldSidePosition)
or ($_POST['sidesOriginal'] !== $sideext)) {
echo "enter";
}
根据这一页。
注意:接受的答案适用于关联数组,但不适用于索引数组(下文解释)。如果你想比较它们中的任何一个,那么使用这个解决方案。此外,此函数可能不适用于多维数组(由于array_diff函数的性质)。
测试两个索引数组,其中元素的顺序不同,使用$a == $b或$a === $b会失败,例如:
<?php
(array("x","y") == array("y","x")) === false;
?>
这是因为上面的意思是:
阵列(0 = > " x ", 1 = > " y ")和数组(0 = > " y ", 1 = > " x ")。
要解决这个问题,请使用:
<?php
function array_equal($a, $b) {
return (
is_array($a)
&& is_array($b)
&& count($a) == count($b)
&& array_diff($a, $b) === array_diff($b, $a)
);
}
?>
添加了比较数组大小(由super_ton建议),因为它可以提高速度。
一种方法:(为https://www.rfc-editor.org/rfc/rfc6902#section-4.6实现“考虑平等”)
这种方式允许关联数组的成员顺序不同——例如,除了php,它们在每种语言中都被认为是相等的:)
// recursive ksort
function rksort($a) {
if (!is_array($a)) {
return $a;
}
foreach (array_keys($a) as $key) {
$a[$key] = ksort($a[$key]);
}
// SORT_STRING seems required, as otherwise
// numeric indices (e.g. "0") aren't sorted.
ksort($a, SORT_STRING);
return $a;
}
// Per https://www.rfc-editor.org/rfc/rfc6902#section-4.6
function considered_equal($a1, $a2) {
return json_encode(rksort($a1)) === json_encode(rksort($a2));
}
下面的解决方案使用可作为回调传递的自定义相等函数。注意,它不检查数组的顺序。
trait AssertTrait
{
/**
* Determine if two arrays have the same elements, possibly in different orders. Elements comparison function must be passed as argument.
*
* @param array<mixed> $expected
* @param array<mixed> $actual
*
* @throws InvalidArgumentException
*/
public static function assertArraysContainSameElements(array $expected, array $actual, callable $comparisonFunction): void
{
Assert::assertEquals(\count($expected), \count($actual));
self::assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes($expected, $actual, $comparisonFunction);
self::assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes($actual, $expected, $comparisonFunction);
}
/**
* @param array<mixed> $needles
* @param array<mixed> $haystack
*
* @throws InvalidArgumentException
*/
private static function assertEveryElementOfArrayIsInAnotherArrayTheSameAmountOfTimes(
array $needles,
array $haystack,
callable $comparisonFunction
): void {
Assert::assertLessThanOrEqual(\count($needles), \count($haystack));
foreach ($needles as $expectedElement) {
$matchesOfExpectedElementInExpected = \array_filter(
$needles,
static fn($element): bool => $comparisonFunction($expectedElement, $element),
);
$matchesOfExpectedElementInActual = \array_filter(
$haystack,
static fn($element): bool => $comparisonFunction($expectedElement, $element),
);
Assert::assertEquals(\count($matchesOfExpectedElementInExpected), \count($matchesOfExpectedElementInActual));
}
}
}
我通常在数据库集成测试中使用它,当我想确保返回预期的元素,但我不关心排序。
if (array_diff($a,$b) == array_diff($b,$a)) {
// Equals
}
if (array_diff($a,$b) != array_diff($b,$a)) {
// Not Equals
}
从我的观点来看,最好使用array_diff而不是array_intersect,因为这种性质的检查通常返回的差异小于相似点,这样bool转换占用的内存更少。
注意,此解决方案适用于普通数组,并补充了上面发布的仅对字典有效的==和===。