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.