valores multidimensionales multidimensional keys elementos comparar array_intersect_assoc array_diff array php arrays recursion diff

php - multidimensionales - recursive array_diff()?



php array_diff() (4)

Hay una función de este tipo implementada en los comentarios de 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; }

La implementación solo maneja dos arreglos a la vez, pero no creo que realmente tenga un problema. Puede ejecutar el diff secuencialmente si necesita la diferencia de 3 o más matrices a la vez. Además, este método usa verificaciones de llaves y realiza una verificación suelta.

Estoy buscando alguna herramienta que me proporcione una diferencia recursiva de dos matrices. Lo que imagino es una página web con dos estructuras de árbol codificadas por colores. En cada árbol, verde son partes de la matriz que coinciden en ambas matrices, y el rojo es para partes de cada una que no coinciden con la otra. Algo así como la salida de dBug

Tengo un código que me da una matriz anidada para completar un informe. Estoy desarrollando un nuevo método que debería ser más rápido, pero necesito probar los valores y también la estructura, para asegurarme de que da salida idéntica al método anterior.

¿Hay algo por ahí que pueda usar? ¿O necesito escribir esto? ¿O hay otra forma de lograr mis objetivos?


La respuesta aceptada es casi correcta, pero en realidad no emula array_diff correctamente.

Hay dos problemas que en gran parte giran en torno a la coincidencia de claves:

  1. array_diff tiene un comportamiento específico donde no produce un resultado para una clave de matriz que falta completamente en la segunda matriz si su valor aún está en la segunda matriz. Si tiene dos matrices $first = [''foo'' => 2, ''moo'' => 2] y $second = [''foo'' => 2] , utilizando la función de la respuesta aceptada, la salida será [''moo'' => 2] . Si ejecuta las mismas matrices a través de array_diff , producirá una matriz vacía. Esto se debe a que la sentencia else anterior de la función anterior la agrega al diff si falta la clave del arreglo, pero ese no es el comportamiento esperado de array_diff . Lo mismo es cierto con estas dos matrices: $first = [''foo'' => 1] y $second = [1] . array_diff producirá una matriz vacía.

  2. Si dos matrices tienen los mismos valores pero claves diferentes, devuelve más valores de los esperados. Si tiene dos matrices $foo = [1, 2] y $moo = [2, 1] , la función de la respuesta aceptada arrojará todos los valores desde $foo . Esto se debe a que realiza una coincidencia de claves estricta en cada iteración donde encuentra la misma clave (numérica o no) en ambas matrices en lugar de verificar todos los demás valores en la segunda matriz.

La siguiente función es similar, pero actúa más de cerca de cómo esperaría que funcionara array_diff (también con menos nombres de variable tontos):

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


Prueba este código:

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


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

Ejemplo:

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

Salida:

array_diff_assoc_recursive($a,$b); Array ( [product_a] => Array ( [color] => Red [serial] => Array ( [2] => 3 ) ) )