2009-04-27 17 views
12

Antecedentes: Trevor está trabajando con una implementación PHP de un algoritmo estándar: tome un conjunto principal de pares nombre-valor predeterminados y actualice esos pares nombre-valor, pero solo para aquellos pares nombre-valor donde un valor de actualización válido en realidad existe.php array_merge sin borrar valores?

Problema: de forma predeterminada, PHP array_merge funciona así ... sobrescribirá un valor no en blanco con un valor en blanco.

$aamain = Array('firstname'=>'peter','age'=>'32','nation'=>''); 
$update = Array('firstname' => '','lastname' => 'griffin', age =>'33','nation'=>'usa'); 

print_r(array_merge($aamain,$update));  
/* 
Array 
(
    [firstname] =>   // <-- update set this to blank, NOT COOL! 
    [age] => 33    // <-- update set this to 33, thats cool 
    [lastname] => griffin // <-- update added this key-value pair, thats cool 
    [nation] => usa   // <-- update filled in a blank, thats cool. 
) 
*/ 

Pregunta: Cuál es la forma menor número de líneas de código para hacer array_merge donde los valores en blanco nunca se sobreescriben los valores ya existentes?

print_r(array_coolmerge($aamain,$update));  
/* 
Array 
(
    [firstname] => peter // <-- don't blank out a value if one already exists! 
    [age] => 33 
    [lastname] => griffin 
    [nation] => usa 

) 
*/ 

ACTUALIZACIÓN: 2016-06-17T11: 51: 54 la cuestión se actualiza con el contexto aclarar y cambiar el nombre de las variables.

+1

¿Qué quiere que suceda con los duplicados? – elzapp

+0

el comportamiento estándar para el manejo de duplicados está bien: el par clave-valor en feebar sobreescribirá el par clave-valor correspondiente en foobar. La * única * diferencia que quiero es nunca dejar que feebar ponga en blanco un valor en foobar. – dreftymac

+0

** Ver también ** (basado en python) http://stackoverflow.com/questions/38987/how-to-merge-two-python-dictionaries-in-a-single-expression/39858#39858 – dreftymac

Respuesta

12

Bueno, si quieres una manera "inteligente" para hazlo, aquí está, pero puede no ser tan fácil de leer como simplemente hacer un ciclo.

$merged = array_merge(array_filter($foo, 'strval'), array_filter($bar, 'strval')); 

edición: o usar + ...

+0

Gracias por eso. Evitar un ciclo puede ser visto como una especie de "ingenio inútil" en algún nivel, pero es bueno no tener que * siempre * usar bucles cuando algo como mapa, seleccionar o una lista de comprensión (como se implementa en algún otro idiomas) parece más conciso. – dreftymac

+3

Usar 'recortar' en lugar de 'strval' también eliminará los elementos que solo contengan espacios en blanco. –

1

Esto colocará duplicados en una nueva matriz, aunque no sé si esto es lo que quiere.

<?php 
    $foobar = Array('firstname' => 'peter','age' => '33',); 
    $feebar = Array('firstname' => '','lastname' => 'griffin',); 
    $merged=$foobar; 
    foreach($feebar as $k=>$v){ 
    if(isset($foobar[$k]))$merged[$k]=array($v,$foobar[$k]); 
    else $merged[$k]=$v; 
    } 
    print_r($merged); 
?> 

Esto simplemente asegurar que feebar nunca se borran una valor en foobar:

<?php 
    $foobar = Array('firstname' => 'peter','age' => '33',); 
    $feebar = Array('firstname' => '','lastname' => 'griffin',); 
    $merged=$foobar; 
    foreach($feebar as $k=>$v) if($v)$merged[$k]=$v; 
    print_r($merged); 
?> 

o por supuesto,

<? 
    function cool_merge($array1,$array2){ 
    $result=$array1; 
    foreach($array2 as $k=>$v) if($v)$result[$k]=$v; 
    return $result; 
    } 

    $foobar = Array('firstname' => 'peter','age' => '33',); 
    $feebar = Array('firstname' => '','lastname' => 'griffin',); 
    print_r(cool_merge($foobar,$feebar)); 
?> 
5

Prueba esto:

$merged = array_map(
    create_function('$foo,$bar','return ($bar?$bar:$foo);'), 
    $foobar,$feebar 
); 

No es la solución más fácil de leer, pero se deben reemplazar sólo los valores no vacíos, independientemente de qué ordenar la arrays se pasan ..

+0

Gracias por eso. – dreftymac

4

ajustamos a sus necesidades:

# Replace keys in $foo 
foreach ($foo as $key => $value) { 
    if ($value != '' || !isset($bar[$key])) continue; 
    $foo[$key] = $bar[$key]; 
} 

# Add other keys in $bar 
# Will not overwrite existing keys in $foo 
$foo += $bar; 
+0

Gracias por eso. – dreftymac

1

Si también desea mantener los valores que están en blanco en ambas matrices:

array_filter($foo) + array_filter($bar) + $foo + $bar 
2
array_replace_recursive($array, $array2); 

Ésta es la solución.

+2

Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación. Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. – JonasCz

+1

Esta es, de lejos, la mejor respuesta aquí. ¡Gracias! – timothymarois

+0

Estoy de acuerdo, esta es la mejor solución aquí. No se necesita explicación La documentación de PHP es suficiente. – GRowing