PHP深度扩展数组

22

我如何对多维关联数组进行深度扩展(用于解码JSON对象)。我需要使用数组而不是JSON并且在PHP中等效于jQuery的$.extend(true, array1, array2)

这里是我需要的示例(array_merge_recursive似乎没有执行相同的操作)

$array1 = ('1'=> ('a'=>'array1a', 'b'=>'array1b'));
$array2 = ('1'=> ('a'=>'array2a', 'c'=>'array2b'));

$array3 = array_extend($array1, $array2);

//$array3 = ('1'=> ('a'=>'array2a', 'b'=>'array1b', 'c'=>'array2b'))

注意,如果array2具有相同的值(就像类的扩展一样),它会覆盖array1。


2
如果您使用的是PHP 5.3.0+,您可以使用array_replace_recursive函数来实现您所需的功能。 - S P
我还没有时间审查所有的答案,但array_replace_recursive肯定是实现这个目标最简单的方法。想把它写成回答,我会接受的。 - Sabrina Leggett
7个回答

26
如果您使用PHP 5.3.0+,则可以使用array_replace_recursive函数,该函数恰好可以实现您所需的功能:

array_replace_recursive()将数组1中的值替换为所有后续数组中相同值的值。如果第一个数组中存在第二个数组中的键,则其值将被第二个数组中的值替换。如果该键存在于第二个数组中而不是第一个数组中,则它将在第一个数组中创建。如果仅存在于第一个数组中,则保留它的值。如果传递了多个用于替换的数组,则会按顺序处理它们,后面的数组将覆盖前面的值。


2
我使用它的方式与我使用angular.extend(dst, src)和jQuery.extend()的方式相同。
function extend($base = array(), $replacements = array()) {
    $base = ! is_array($base) ? array() : $base;
    $replacements = ! is_array($replacements) ? array() : $replacements;

    return array_replace_recursive($base, $replacements);
}

示例:

si() 是一个实用的清理函数,可以获取 $_POST 或 $_GET 并返回一个数组。

        $s = extend(array(
            'page' => 1,
            'take' => 100,
            'completed' => 1,
            'incomplete' => 1,
        ), si());

2
这可能是你正在寻找的内容:
function array_extend(&$result) {
  if (!is_array($result)) {
    $result = array();
  }

  $args = func_get_args();

  for ($i = 1; $i < count($args); $i++) {
    // we only work on array parameters:
    if (!is_array($args[$i])) continue;

    // extend current result:
    foreach ($args[$i] as $k => $v) {
      if (!isset($result[$k])) {
        $result[$k] = $v;
      }
      else {
        if (is_array($result[$k]) && is_array($v)) {
          array_extend($result[$k], $v);
        }
        else {
          $result[$k] = $v;
        }
      }
    }
  }

  return $result;
}

使用方法:

$arr1 = array('a' => 1, 'b' => 2, 'c' => 3);
$arr2 = array('b' => 'b', 'd' => 'd');
array_extend($arr1, $arr2);
print_r($arr1); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')

// or, to create a new array and leave $arr1 unchanged use:
array_extend($arr3, $arr1, $arr2);
print_r($arr3); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')

// or, use the return value:
print_r(array_extend($arr1, $arr2)); // but this will also modify $arr1

1
您应该使用: https://github.com/appcia/webwork/blob/master/lib/Appcia/Webwork/Storage/Config.php#L64
/**
 * Merge two arrays recursive
 *
 * Overwrite values with associative keys
 * Append values with integer keys
 *
 * @param array $arr1 First array
 * @param array $arr2 Second array
 *
 * @return array
 */
public static function merge(array $arr1, array $arr2)
{
    if (empty($arr1)) {
        return $arr2;
    } else if (empty($arr2)) {
        return $arr1;
    }

    foreach ($arr2 as $key => $value) {
        if (is_int($key)) {
            $arr1[] = $value;
        } elseif (is_array($arr2[$key])) {
            if (!isset($arr1[$key])) {
                $arr1[$key] = array();
            }

            if (is_int($key)) {
                $arr1[] = static::merge($arr1[$key], $value);
            } else {
                $arr1[$key] = static::merge($arr1[$key], $value);
            }
        } else {
            $arr1[$key] = $value;
        }
    }

    return $arr1;
}

1
取自array_merge文档:
function array_extend($a, $b) {
    foreach($b as $k=>$v) {
        if( is_array($v) ) {
            if( !isset($a[$k]) ) {
                $a[$k] = $v;
            } else {
                $a[$k] = array_extend($a[$k], $v);
            }
        } else {
            $a[$k] = $v;
        }
    }
    return $a;
}

1
@Baba 在编辑/发布时,您可以在某个地方检查“社区”。 - Yoshi
@xdazz 我认为这个问题只是一种声望获取的尝试。由同一用户立即提出并回答。 - Yoshi
1
@xdazz 当我发现一些我曾经费劲心思搜索的东西时,我会把它们放在这里 - 这样将来我就不必再费那么大力气去寻找了 :-) 不确定这是否是正确的地方,但我注意到了 QA 样式选项,所以我想这应该没问题。希望对其他人也有所帮助.....或者也许我只是一个回复狂...我想你永远都不会知道! - Sabrina Leggett

0

我认为这里是正确的答案,因为:

  • 你的答案有一个警告错误:

    Warning: Cannot use a scalar value as an array in...

因为 $a 不总是一个数组,而你使用了 $a[$k]。

  • array_merge_recursive 确实合并数组,但它将具有重复键的值转换为数组,而不是像 array_merge 一样用第二个数组中的重复值覆盖第一个数组中的值。

  • 其他答案要么不是递归的,要么不够简单。

所以,这就是我的答案:没有错误的答案。

function array_extend(array $a, array $b) {
    foreach($b as $k=>$v) {
        if( is_array($v) ) {
            if( !isset($a[$k]) ) {
                $a[$k] = $v;
            } else {
                if( !is_array($a[$k]){
                    $a[$k]=array();
                }
                $a[$k] = array_extend($a[$k], $v);
            }
        } else {
            $a[$k] = $v;
        }
    }
    return $a;
}

我的答案使用三元运算符:

function array_extend(array $a, array $b){
    foreach($b as $k=>$v)
            $a[$k] = is_array($v)&&isset($a[$k])?
                array_extend(is_array($a[$k])?
                        $a[$k]:array(),$v):
                $v;
    return $a;
}

编辑:还有一个额外的,你可以使用任意数量的数组:

function array_extend(){
    $args = func_get_args();
    while($extended = array_shift($args))
            if(is_array($extended))
                    break;
    if(!is_array($extended))
            return FALSE;
    while($array = array_shift($args)){
        if(is_array($array))
                foreach($array as $k=>$v)
                        $extended[$k] = is_array($v)&&isset($extended[$k])?
                            array_extend(is_array($extended[$k])?
                                    $extended[$k]:array(),$v):
                            $v;
    }
    return $extended;
}

0

通过简单的谷歌搜索,我找到了这个:

/**
 * jquery style extend, merges arrays (without errors if the passed values are not arrays)
 *
 * @return array $extended
 **/
function extend() {
    $args = func_get_args();
    $extended = array();
    if(is_array($args) && count($args)) {
        foreach($args as $array) {
            if(is_array($array)) {
                $extended = array_merge($extended, $array);
            }
        }
    }
    return $extended;
}

extend($defaults, $new_options);

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