我有一些代码,可以给我一个嵌套的数组来填充报告。我正在开发一种新方法,应该会更快,但我需要测试值和结构,以确保它的输出与旧方法完全相同。
是否有可用的工具?还是我需要编写代码?或者还有其他实现目标的方法吗?
在array_diff的注释中实现了这样一个函数。
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if ($mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
该实现一次仅处理两个数组,但我认为这并不会导致问题。如果需要同时比较三个或更多的数组,则可以按顺序运行差异。此外,此方法使用关键字检查和进行宽松验证。
if ($mValue !== $aArray2[$mKey]) {
,这样它也会检测到值类型的变化。 - KoalaBear$a = [1,2,3,4]; $b = [4,5,6,7]; arrayRecursiveDiff($a, $b);
- klipach被接受的答案接近正确,但它并没有真正正确地模拟array_diff
。
存在两个问题,其主要围绕键匹配:
array_diff
有一个特定的行为,即如果第二个数组完全缺少数组键,并且该键值仍在第二个数组中,则不会为其产生结果。 如果您有两个数组$first = ['foo' => 2, 'moo' => 2]
和$second = ['foo' => 2]
,使用被接受的答案的函数,输出将为['moo' => 2]
。 如果您将相同的数组通过array_diff
运行,它将产生一个空数组。 这是因为上述函数的最终else
语句将其添加到差异中,如果数组键不存在,但这不是来自array_diff
期望的行为。对于这两个数组也是如此:$first = ['foo' => 1]
和 $second = [1]
。array_diff
将产生一个空数组。
如果两个数组具有相同的值但具有不同的键,则返回的值比预期的多。如果您有两个数组$foo = [1, 2]
和$moo = [2, 1]
,则被接受的答案的函数将输出来自$foo
的所有值。这是因为它在每次迭代中进行严格的键匹配,在其中它找到在两个数组中具有相同键(数字或其他)的情况下,而不是检查第二个数组中的所有其他值。
以下函数类似,但更接近于您对array_diff
的预期工作方式(同时使用更少的愚蠢变量名):
function array_diff_recursive($arr1, $arr2)
{
$outputDiff = [];
foreach ($arr1 as $key => $value)
{
//if the key exists in the second array, recursively call this function
//if it is an array, otherwise check if the value is in arr2
if (array_key_exists($key, $arr2))
{
if (is_array($value))
{
$recursiveDiff = array_diff_recursive($value, $arr2[$key]);
if (count($recursiveDiff))
{
$outputDiff[$key] = $recursiveDiff;
}
}
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
//if the key is not in the second array, check if the value is in
//the second array (this is a quirk of how array_diff works)
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
return $outputDiff;
}
array_diff
的不同之处。 - treeface$a = [ "foo"=>(object)["p1"=>1, "p2"=>2], "moo"=>(object)["p3"=>3]]
,$b=[ "foo" => (object)["p4"=>4]]
。 - Max Ivak[1,2]
被认为与数组 [2,1]
不同。这就是为什么我们有函数来添加元素到数组的开头或结尾,而不仅仅是向数组(集合)中添加元素的原因。
如果你想要将数组看作一个集合,那么就需要另一个函数来比较数组作为集合的情况。 - Max Ivakfunction array_diff_assoc_recursive($array1, $array2)
{
foreach($array1 as $key => $value){
if(is_array($value)){
if(!isset($array2[$key]))
{
$difference[$key] = $value;
}
elseif(!is_array($array2[$key]))
{
$difference[$key] = $value;
}
else
{
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if($new_diff != FALSE)
{
$difference[$key] = $new_diff;
}
}
}
elseif((!isset($array2[$key]) || $array2[$key] != $value) && !($array2[$key]===null && $value===null))
{
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
例子:
$a = array(
"product_a" => array(
'description'=>'Product A',
'color'=>'Red',
'quantity'=>'5',
'serial'=>array(1,2,3)
),
"product_b" => array(
'description'=>'Product B'
)
);
$b = array(
"product_a" => array(
'description'=>'Product A',
'color'=>'Blue',
'quantity'=>'5',
'serial'=>array(1,2,5)
),
"product_b" => array(
'description'=>'Product B'
)
);
输出:
array_diff_assoc_recursive($a,$b);
Array
(
[product_a] => Array
(
[color] => Red
[serial] => Array
(
[2] => 3
)
)
)
function arrayDiffRecursive($firstArray, $secondArray, $reverseKey = false)
{
$oldKey = 'old';
$newKey = 'new';
if ($reverseKey) {
$oldKey = 'new';
$newKey = 'old';
}
$difference = [];
foreach ($firstArray as $firstKey => $firstValue) {
if (is_array($firstValue)) {
if (!array_key_exists($firstKey, $secondArray) || !is_array($secondArray[$firstKey])) {
$difference[$oldKey][$firstKey] = $firstValue;
$difference[$newKey][$firstKey] = '';
} else {
$newDiff = arrayDiffRecursive($firstValue, $secondArray[$firstKey], $reverseKey);
if (!empty($newDiff)) {
$difference[$oldKey][$firstKey] = $newDiff[$oldKey];
$difference[$newKey][$firstKey] = $newDiff[$newKey];
}
}
} else {
if (!array_key_exists($firstKey, $secondArray) || $secondArray[$firstKey] != $firstValue) {
$difference[$oldKey][$firstKey] = $firstValue;
$difference[$newKey][$firstKey] = $secondArray[$firstKey];
}
}
}
return $difference;
}
$differences = array_replace_recursive(
arrayDiffRecursive($firstArray, $secondArray),
arrayDiffRecursive($secondArray, $firstArray, true)
);
var_dump($differences);
Mohamad的答案很好,只是需要在这一行进行更改:
$difference[$newKey][$firstKey] = $secondArray[$firstKey];
使用:
$difference[$newKey][$firstKey] = array_key_exists($firstKey, $secondArray) ? $secondArray[$firstKey] : null;
或者,如果你正在使用 Laravel,可以使用以下代码:
$difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);
当 $secondArray 中存在 some_key,但 $firstArray 中不存在该键时。PHP 错误:未定义索引:some_key
提供的PHP代码中的函数arrayRecursiveDiff()有助于递归地比较关联数组。它遍历第一个数组中的每个元素,并将其与第二个数组中的相应元素进行比较。如果第一个数组中的元素也是一个数组,则该函数会递归地检查这些子数组的差异。该函数从第一个数组中收集所有在第二个数组中不存在(或不同)的唯一元素,包括嵌套数组中的元素,并将它们作为关联数组返回。这实际上是对array_diff()函数的递归版本,它适用于关联数组并支持多维数组。
function arrayRecursiveDiff(array $array1, array $array2): array
{
$aReturn = [];
foreach ($array1 as $index => $value) {
if (array_key_exists($index, $array2)) {
if (is_array($value) && is_array($array2[$index])) {
$recursiveDiff = arrayRecursiveDiff($value, $array2[$index]);
if ($recursiveDiff !== []) {
$aReturn[$index] = $recursiveDiff;
}
} elseif ($value !== $array2[$index]) {
$aReturn[$index] = $value;
}
} else {
$aReturn[$index] = $value;
}
}
return $aReturn;
}
$array1 = ['test' => 'test', 'test2' => 'test2', 'test3' => ['test4' => 'test4', 'test5' => 'test5']];
$array2 = ['test' => 'test', 'test2' => 'test2', 'test3' => ['test4' => 'test4', 'test5' => ['test6' => 'test6', 'test7' => 'test7']]];
print_r(arrayRecursiveDiff($array2,$array1));
wdiff
命令覆盖var_export
输出就可以解决问题了... - Wrikkenwdiff
出现问题吗?因为在输出中,比如从第0行到第30行,它们是相同的,从末尾返回到第36行也是相同的。只有那些中间行是不同的--3与6。如果wdiff查看这个,它会被卡住吗? - user151841