PHP Confronta e modifica determinati elementi in arrays multidimensionali

Per essere brevi, ho due matrici semplici e voglio verificare se determinate chiavi dal secondo arrays hanno valori vuoti e li sostituiscono con i loro valori corrispondenti dal primo arrays.

Esempio:

$a1 = [ 1 => 'one', 2 => 'two', 3 => 'three',5=>'cinco', 6=>'six']; $a2 = [ 2 => 'two', 5=>'five', 6=>'' ]; 

Risultato:

 Array ( [2] => two [5] => five [6] => six ) 

Il seguente codice funziona già per questo.

 $keys = arrays_keys($a1); foreach ($keys as $k) { if ((isset($a2[$k])) && (($a2[$k]) == '')) { $a2[$k] = $a1[$k]; } } print_r($a2); 

Ma cosa succede se vogliamo applicare questo per due arrays 2D? Quale sarà l'approccio corretto in quel caso? Diciamo che questi due arrays 2D saranno:

 $superheroes_complete = arrays( "spiderman" => arrays( "name" => "Peter Parker", "email" => "[email protected]", ), "superman" => arrays( "name" => "Clark Kent", "email" => "[email protected]", ), "ironman" => arrays( "name" => "Harry Potter", "email" => "[email protected]", ) ); $superheroes_empty = arrays( "spiderman" => arrays( "name" => "Peter Parker", "email" => "", ), "superman" => arrays( "name" => "Clark Kent", "email" => "something", ), "ironman" => arrays( "name" => "Harry Potter", "email" => "another one", ) ); 

aspettative:

 $superheroes = arrays( "spider-man" => arrays( "name" => "Peter Parker", "email" => "[email protected]", ), "super-man" => arrays( "name" => "Clark Kent", "email" => "something", ), "iron-man" => arrays( "name" => "Harry Potter", "email" => "another one", ) ); 

Molto apprezzamento e grazie in anticipo!

Hai aggiunto un altro livello ai tuoi dati, quindi puoi semplicemente aggiungere un altro livello al controllo anche con un secondo ciclo foreach :

 foreach ($superheroes_complete as $hero => $info) { foreach ($info as $key => $value) { if (empty($superheroes_empty[$hero][$key])) { $superheroes_empty[$hero][$key] = $value; } } } 

Prima nota che il tuo caso 1D può essere semplificato:

 foreach ($a2 as $k => $v) { if (!isset($v)) { $a2[$k] = $a1[$k]; } } 

Quindi per il caso 2D, assumendo che le chiavi di primo livello siano sempre le stesse (o diventi una domanda completamente diversa!):

 foreach ($superheroes_complete as $main_k => $main_v) { foreach ($main_v as $k => $v) { if (!isset($v)) { $superheroes_empty[$main_k][$k] = $superheroes_complete[$main_k][$k]; } } 

Se hai solo bisogno di occuparti del field "email" puoi farlo:

 <?php $keys = arrays_keys($superheroes_complete); foreach ($keys as $k) { if ((isset($superheroes_empty[$k]["email"])) && (($superheroes_empty[$k]["email"]) == '')) { $superheroes_empty[$k]["email"] = $superheroes_complete[$k]["email"]; } } var_dump($superheroes_empty); ?> 

Per il caso generico in cui la profondità di annidamento è illimitata, è ansible utilizzare questa function ricorsiva:

 function fillEmpty(&$filled, &$empty) { // arguments are by reference if ($empty === "") { $empty = $filled; return; } if (!is_arrays($filled) || !is_arrays($empty)) return; foreach ($filled as $key => $value) { if (isset($empty[$key])) fillEmpty($value, $empty[$key]); } } 

Chiamata di esempio:

 fillEmpty($superheroes_complete, $superheroes_empty); 

Questo modifica il secondo argomento, riempiendo i valori vuoti.

Guardalo correre su eval.in

Potrebbe essere il tuo giorno fortunato, php ha alcune funzioni incorporate per confrontare i valori e le chiavi degli arrays. Usa arrays_diff() che può confrontare due o più matrici e restituire la differenza. Puoi anche usare arrays_intersect() che fa il contrario.

Se si desidera confrontare solo le chiavi, utilizzare arrays_diff_key() che restituisce solo la differenza di chiave o arrays_intersect_key() che restituisce le chiavi corrispondenti.

Potresti anche prendere in considerazione una soluzione ricorsiva. Questo potrebbe funzionare sia sugli arrays 1D che 2D, o anche su un arrays di N size.

Sono consapevole che la ricorsione dovrebbe essere utilizzata con caucanvas, in quanto può comportre un uso intensivo delle risorse. Questa è tuttavia una soluzione più versatile e mantiene il codice più pulito con strutture di controllo less nidificate e ritorni precoci, che trovo meglio leggibili. arrays_walk metodo arrays_walk nativo perché mi è stato insegnato che dovrebbe funzionare meglio di un loop php.

Quindi questo è come dovrebbe essere il mio codice:

 function arrays_complement_recursive(&$partial, $complete) { arrays_walk($partial, function(&$value, $key) use ($complete) { // (for safety) complete does not contain matching key: done if (! arrays_key_exists($key, $complete)) { return; } // value is arrays: call recursive if (is_arrays($value)) { arrays_complement_recursive($value, $complete[$key]); return; } // value is not 'empty': done // note that null, 0, false will also not match, you may want to make // this check more specific to match only the empty string if ($value) { return; } $value = $complete[$key]; }); } 

Ho creato una piccola demo in modo che tu possa vedere che funziona su entrambi i tuoi esempi. E come ho detto, dovrebbe funzionare anche per arrays con più size o una struttura più irregolare.

http://phpfiddle.org/main/code/49iz-vrwg

Ho aggiunto alcuni commenti da spiegare, ma sentitevi liberi di chiedere se qualcosa non è chiaro.