不删除值的PHP array_merge?

15

背景:特雷弗正在使用PHP实现一个标准算法:获取一组默认的键值对,然后仅更新那些存在有效更新值的键值对。

问题:默认情况下,PHP的array_merge函数会覆盖非空值为一个空值的情况。

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

问题: 怎样用最少的代码行实现array_merge,而且空值不会覆盖已有的值?

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

)
*/

更新:2016-06-17T11:51:54 该问题已更新,澄清了上下文并重命名了变量。


1
你希望对重复项进行什么操作? - elzapp
处理重复项的标准行为是可以接受的:feebar 中的键值对将覆盖 foobar 中相应的键值对。我想要的唯一区别是永远不要让 feebar 抹掉 foobar 中的值。 - dreftymac
另请参阅(基于Python)https://dev59.com/43VD5IYBdhLWcg3wQJOT#39858 - dreftymac
参见(基于Python)https://dev59.com/A2w15IYBdhLWcg3w3fjN - dreftymac
参见(php zeroes)https://dev59.com/qmYq5IYBdhLWcg3w30Tc - dreftymac
6个回答

16

如果你想要一种“聪明”的方式来做到这一点,那么这里就有一种方法,但它可能不像简单的循环那样易读。

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

编辑:或者使用 + …


谢谢你的回复。避免使用循环可能在某种程度上被视为一种“无用的聪明” - 但是,当像map、select或列表推导(如其他一些语言中实现的那样)这样的东西更简洁时,不必总是使用循环是很好的。 - dreftymac
3
使用“trim”而不是“strval”也会清除仅包含空格的项目。 - too much php

5

试试这个:

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

这不是最易读的解决方案,但它应该只替换非空值,无论以哪种顺序传递数组。


5
array_replace_recursive($array, $array2);

这是解决方案。


4
尽管这段代码片段可能解决了问题,但包括解释真的有助于提高您发布内容的质量。请记住,您正在为将来的读者回答问题,而那些人可能不知道您提出代码建议的原因。 - Jonas Czech
3
这绝对是最好的答案。谢谢! - tmarois
1
我同意,这是这里最好的解决方案。不需要解释。PHP文档已经足够了。 - GRowing
1
我是否漏掉了什么,或者这根本不是OP所问的?使用此答案,OP的结果将为:{["firstname"]=>"",["age"]=>"33",["nation"]=>"usa",["lastname"]=>"griffin"}。 - Tum

4

根据您的需求进行调整:

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

2
如果您还想保留两个数组中都为空的值:
array_filter($foo) + array_filter($bar) + $foo + $bar

1

这将把重复的元素放入一个新数组中,但我不确定这是否符合您的要求。

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

这将确保feebar永远不会在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);
?>

或者当然也可以,

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接