PHP递归合并

8
我需要以不同的方式合并一些数组,并使用array_merge_recursive。但是有一些需要更改的内容,我不知道该怎么做。以下是来自php.net的引用:
如果数组具有相同的数字键,则后面的值将不会覆盖原始值,而是将被追加。
我希望这个值不被追加,我不想在新数组中追加精确的值。希望你已经理解了这一点。
例子:
$array = array(
   'some'  => array(
       'other'    => 'key',
   ),
);

$array2 = array();
$array2['some']['other'] = 'key2';

如果我使用array_merge_recursive,结果会是这样的:
Array (
    [some] => Array
        (
            [other] => Array
                (
                    [0] => key
                    [1] => key2
                )
        ) )

我希望如果匹配到相同的结果,不要将其附加在后面。我知道你可能会说,可以使用array_merge,但它也不能很好地工作。 如果我使用以下方法:

$array = array(
   'some'  => array(
       'other'    => 'key',
   ),
);

$array2 = array();
$array2['some']['other2'] = 'key2';

print_r(array_merge($array, $array2));

它将从列表中移除 $array[some][other] ,只保留 $array[some][other2]。我不知道哪一个更好,因为没有人做得更好。


1
你的数组嵌套有多深?只有一层吗? - hakre
1
那告诉我们你的结果应该是什么? - scube
可能是无限的。我不会只用它在一个层级上。 - Alex Emilov
@scube 如果使用array_merge函数,结果应该是不会从第一个数组中删除先前的项。第二个示例显示:Array ( [some] => Array ( [other2] => key2 ))我想要显示的是:Array ( [some] => Array ( [other] => key [other2] => key2 )) - Alex Emilov
1
@Alex:当使用array_merge_recursive时,你期望执行以下内容:$array = array( 'some' => array( 'other' => 'key', ), ); $array2['some']['other'] = 'key2'; - scube
我想解释一下,递归并不符合我的需求。也许标题让你感到困惑了,抱歉。 - Alex Emilov
5个回答

7

5

试一下

<?php
function mymerge(&$a,$b){ //$a will be result. $a will be edited. It's to avoid a lot of copying in recursion
    foreach($b as $child=>$value){
        if(isset($a[$child])){ 
            if(is_array($a[$child]) && is_array($value)){ //merge if they are both arrays
                mymerge($a[$child],$value);
            }
            //else ignore, you can add your own logic, i.e when 1 of them is array
        }
        else
            $a[$child]=$value; //add if not exists
    }

    //return $a;
}

这个答案可能不正确。因为我测试了你的答案,结果并不像我预期的那样。 你能看一下这个链接吗? 链接 - Murat Çakmak

2
另一个选择是来自Drupal的array_merge_deep函数:
function array_merge_deep($arrays) {
  $result = array();
  foreach ($arrays as $array) {
    foreach ($array as $key => $value) {
      // Renumber integer keys as array_merge_recursive() does. Note that PHP
      // automatically converts array keys that are integer strings (e.g., '1')
      // to integers.
      if (is_integer($key)) {
        $result[] = $value;
      }
      // Recurse when both values are arrays.
      elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
        $result[$key] = array_merge_deep(array($result[$key], $value));
      }
      // Otherwise, use the latter value, overriding any previous value.
      else {
        $result[$key] = $value;
      }
    }
  }
  return $result;
}

1

我从RiaD的版本开始,并添加了对象处理。需要测试和反馈。

function recursiveMerge(&$a,$b){ //$a will be result. $a will be edited. It's to avoid a lot of copying in recursion
        if(is_array($b) || is_object($b)){
            foreach($b as $child=>$value){
                if(is_array($a)){
                    if(isset($a[$child]))
                        recursiveMerge($a[$child],$value);
                    else
                        $a[$child]=$value;
                }
                elseif(is_object($a)){
                    if(isset($a->{$child}))
                        recursiveMerge($a->{$child},$value);
                    else
                        $a->{$child}=$value;
                }
            }
        }
        else
            $a=$b;
    }

1
我为此编写了合并类:

<?php

class ArrayMerge
{

    /**
     * @param array $a
     * @param array $b
     *
     * @return array
     */
    public function merge ( $a, $b ) {
        foreach ( $b as $k => $v ) {
            if ( is_array( $v ) ) {
                if ( isset( $a[ $k ] ) ) {
                    if ( $this->isDeep( $v ) ) {
                        $a[ $k ] = $this->merge( $a[ $k ], $v );
                    } else {
                        $a[ $k ] = array_merge( $a[ $k ], $v );
                    }
                } else {
                    $a[ $k ] = $v;
                }
            } else {
                $a[ $k ] = $v;
            }
        }
        return $a;
    }

    /**
     * @param array $array
     *
     * @return bool
     */
    private function isDeep ( $array ) {
        foreach ( $array as $elm ) {
            if ( is_array( $elm ) ) {
                return TRUE;
            }
        }
        return FALSE;
    }

}

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