16

Background: Trevor is working with a PHP implementation of a standard algorithm: take a main set of default name-value pairs, and update those name-value pairs, but only for those name-value pairs where a valid update value actually exists.

Problem: by default, PHP array_merge works like this ... it will overwrite a non-blank value with a blank value.

$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.
)
*/

Question: What's the fewest-lines-of-code way to do array_merge where blank values never overwrite already-existing values?

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

)
*/

UPDATE: 2016-06-17T11:51:54 the question was updated with clarifying context and rename of variables.

5
  • 1
    What do you want to happen with the duplicates? Commented Apr 27, 2009 at 13:26
  • the standard behavior for handling duplicates is fine: the key-value pair in feebar will overwrite the corresponding key-value pair in foobar. The only difference I want is to never let feebar blank out a value in foobar. Commented Apr 27, 2009 at 13:40
  • See also (python-based) stackoverflow.com/questions/38987/… Commented Dec 28, 2016 at 19:26
  • See also (python-based) stackoverflow.com/q/6354436/42223 Commented Jan 1, 2017 at 21:23
  • See also (php zeroes) stackoverflow.com/questions/14134006/… Commented Apr 18, 2018 at 15:30

6 Answers 6

16

Well, if you want a "clever" way to do it, here it is, but it may not be as readable as simply doing a loop.

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

edit: or using +...

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that one. Avoiding a loop can be seen as a kind of "useless cleverness" on some level perhaps -- but it's just nice to not have to always use loops when something like map, select, or a list comprehension (as implemented in some other languages) seems more concise.
Using 'trim' instead of 'strval' will also clear out items which only contain whitespace.
5

Try this:

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

Not the most readable solution, but it should replace only non-empty values, regardless of which order the arrays are passed..

Comments

4
array_replace_recursive($array, $array2);

This is the solution.

4 Comments

While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
I agree, this is the best solution here. No explanation needed. PHP documentation is sufficient.
Am I missing something or isn't this at all what OP asked? OP's result using this answer would be: { ["firstname"] => "", ["age"] => "33", ["nation"] => "usa", ["lastname"] => "griffin" }
This is NOT the solution, this will overwrite existing values. onlinephp.io/c/cfb52
4

Adjust to your needs:

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

Comments

2

If you also want to keep the values that are blank in both arrays:

array_filter($foo) + array_filter($bar) + $foo + $bar

Comments

1

This will put duplicates into a new array, I don't know if this is what you want though.

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

This will simply assure that feebar will never blank out a value in 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);
?>

or ofcourse,

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.