ricorsivo arrays_diff ()?

Sto cercando uno strumento per darmi una differenza ricorsiva di due arrays. Quello che immagino è una pagina web con due strutture ad tree con codice colore. Su each tree, il verde sono parti dell'arrays che corrispondono in entrambi gli arrays e il rosso è per parti di ciascuna che non corrispondono all'altro. Qualcosa come l'output di dBug

Ho del codice che mi fornisce una matrix annidata per popolare un rapporto. Sto sviluppando un nuovo metodo che dovrebbe essere più veloce, ma ho bisogno di testare i valori e anche la struttura, per assicurarmi che fornisca l'output identico al vecchio metodo.

C'è qualcosa là fuori che posso usare? O devo scrivere questo? O c'è un altro modo per raggiungere i miei obiettivi?

Esiste una function di questo tipo implementata nei commenti di arrays_diff .

 function arraysRecursiveDiff($aArray1, $aArray2) { $aReturn = arrays(); foreach ($aArray1 as $mKey => $mValue) { if (arrays_key_exists($mKey, $aArray2)) { if (is_arrays($mValue)) { $aRecursiveDiff = arraysRecursiveDiff($mValue, $aArray2[$mKey]); if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; } } else { if ($mValue != $aArray2[$mKey]) { $aReturn[$mKey] = $mValue; } } } else { $aReturn[$mKey] = $mValue; } } return $aReturn; } 

L'implementazione gestisce solo due arrays alla volta, ma non credo che sia davvero un problema. È ansible eseguire la diff in sequenza se è necessario il diff di 3 o più matrici alla volta. Anche questo metodo utilizza i controlli chiave e fa una verifica libera.

La risposta accettata è quasi corretta, ma in realtà non emula correttamente arrays_diff .

Ci sono due problemi che ruotano in gran parte attorno alla corrispondenza delle chiavi:

  1. arrays_diff ha un comportmento specifico in cui non produce un risultato per una chiave di arrays che manca completamente dal secondo arrays se il suo valore è ancora nel secondo arrays. Se hai due arrays $first = ['foo' => 2, 'moo' => 2] e $second = ['foo' => 2] , usando la function della risposta accettata l'output sarà ['moo' => 2] . Se si eseguono gli stessi arrays tramite arrays_diff , verrà generato un arrays vuoto. Ciò è dovuto al fatto che l'istruzione else finale della function precedente la aggiunge al diff se manca la chiave dell'arrays, ma questo non è il comportmento previsto da arrays_diff . Lo stesso vale per questi due arrays: $first = ['foo' => 1] e $second = [1] . arrays_diff produrrà una matrix vuota.

  2. Se due arrays hanno gli stessi valori ma chiavi diverse, restituisce più valori del previsto. Se hai due matrici $foo = [1, 2] e $moo = [2, 1] , la function dalla risposta accettata produrrà tutti i valori da $foo . Questo perché sta eseguendo un rigoroso abbinamento di chiavi su each iterazione in cui trova la stessa chiave (numbersca o less) in entrambi gli arrays invece di controllare tutti gli altri valori nel secondo arrays.

La seguente function è simile, ma agisce più da vicino come si dovrebbe aspettare che arrays_diff funzioni (anche con nomi di variables less stupidi):

 function arrays_diff_recursive($arr1, $arr2) { $outputDiff = []; foreach ($arr1 as $key => $value) { //if the key exists in the second arrays, recursively call this function //if it is an arrays, otherwise check if the value is in arr2 if (arrays_key_exists($key, $arr2)) { if (is_arrays($value)) { $recursiveDiff = arrays_diff_recursive($value, $arr2[$key]); if (count($recursiveDiff)) { $outputDiff[$key] = $recursiveDiff; } } else if (!in_arrays($value, $arr2)) { $outputDiff[$key] = $value; } } //if the key is not in the second arrays, check if the value is in //the second arrays (this is a quirk of how arrays_diff works) else if (!in_arrays($value, $arr2)) { $outputDiff[$key] = $value; } } return $outputDiff; } 
 function arrays_diff_assoc_recursive($arrays1, $arrays2) { foreach($arrays1 as $key => $value){ if(is_arrays($value)){ if(!isset($arrays2[$key])) { $difference[$key] = $value; } elseif(!is_arrays($arrays2[$key])) { $difference[$key] = $value; } else { $new_diff = arrays_diff_assoc_recursive($value, $arrays2[$key]); if($new_diff != FALSE) { $difference[$key] = $new_diff; } } } elseif((!isset($arrays2[$key]) || $arrays2[$key] != $value) && !($arrays2[$key]===null && $value===null)) { $difference[$key] = $value; } } return !isset($difference) ? 0 : $difference; } 

Esempio:

 $a = arrays( "product_a" => arrays( 'description'=>'Product A', 'color'=>'Red', 'quantity'=>'5', 'serial'=>arrays(1,2,3) ), "product_b" => arrays( 'description'=>'Product B' ) ); $b = arrays( "product_a" => arrays( 'description'=>'Product A', 'color'=>'Blue', 'quantity'=>'5', 'serial'=>arrays(1,2,5) ), "product_b" => arrays( 'description'=>'Product B' ) ); 

Produzione:

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

Prova questo codice:

 function arraysDiffRecursive($firstArray, $secondArray, $reverseKey = false) { $oldKey = 'old'; $newKey = 'new'; if ($reverseKey) { $oldKey = 'new'; $newKey = 'old'; } $difference = []; foreach ($firstArray as $firstKey => $firstValue) { if (is_arrays($firstValue)) { if (!arrays_key_exists($firstKey, $secondArray) || !is_arrays($secondArray[$firstKey])) { $difference[$oldKey][$firstKey] = $firstValue; $difference[$newKey][$firstKey] = ''; } else { $newDiff = arraysDiffRecursive($firstValue, $secondArray[$firstKey], $reverseKey); if (!empty($newDiff)) { $difference[$oldKey][$firstKey] = $newDiff[$oldKey]; $difference[$newKey][$firstKey] = $newDiff[$newKey]; } } } else { if (!arrays_key_exists($firstKey, $secondArray) || $secondArray[$firstKey] != $firstValue) { $difference[$oldKey][$firstKey] = $firstValue; $difference[$newKey][$firstKey] = $secondArray[$firstKey]; } } } return $difference; } $differences = arrays_replace_recursive( arraysDiffRecursive($firstArray, $secondArray), arraysDiffRecursive($secondArray, $firstArray, true) ); var_dump($differences);