云客Drupal源码分析之合并数组

在drupal的源码实现中有非常多的合并数组操作,这本是php层面的知识,但鉴于用的如此之多,而且drupal还专门实现了一种合并方法,所以特别设置一个主题来讲解。
合并php数组主要有以下几个方法:
1:通过“+”操作符号进行数组相加的前保留合并
2:函数:array_merge 后保留合并
3:array_merge_recursive 递归且全保留合并
4:drupal实现的条件式合并

通过“+”操作符号进行数组相加

直接将两个数组通过“+”操作符相加,是一种前保留合并,就是说如果键名相同,包括数字索引键名,则前面的覆盖后面的,以前值为准,使用时需特别注意数字索引问题,它的特征是完全保留前面的数组,如:

 

$a=["a"=>1,"b"=>2,"c"=>3 ,"a"];
$b=["a"=>4,"d"=>5,"c"=>6 ,"b"];
$c=$a+$b;
那么$c将是["a"=>1,"b"=>2,"c"=>3,"a",d"=>5];


函数:array_merge
此函数实现的是后保留合并,有相同的键名时,后面的将覆盖前面的值,但数字索引键名即便相同也不覆盖,而是全部保留并重新索引,特征是后保留且数字索引均保留,如:

 

$a=["a"=>1,"b"=>2,"c"=>3,"a"];
$b=["a"=>4,"d"=>5,"c"=>6,"b"];
$c=array_merge($a,$b);
那么$c将是["a"=>4,"b"=>2,"c"=>6,"a",d"=>5,"b"];


此函数官方文档请见:http://php.net/manual/zh/function.array-merge.php

array_merge_recursive 递归合并
此函数是一种全保留的合并,将所有数组的值都保留下来,特征是不覆盖,将本会覆盖的值合并组成新数组,数字索引将重新索引,这个过程是递归的,如:

 

 

$a = ["a" => ["a1", "a2"], "b" => ["b1", "b2"], "c" => 3, "a"];
$b = ["a" => 4, "d" => 5, "c" => 6, "b", "b" => ["b1", "b3"]];
$c = array_merge_recursive($a, $b);
那么$c将是:
Array
(
    [a] => Array
        (
            [0] => a1
            [1] => a2
            [2] => 4
        )

    [b] => Array
        (
            [0] => b1
            [1] => b2
            [2] => b1
            [3] => b3
        )

    [c] => Array
        (
            [0] => 3
            [1] => 6
        )

    [0] => a
    [d] => 5
    [1] => b
)
怎么理解“递归”呢?如下:
$a = ["a" => ["b" => ["c" => 1]]];
$b = ["a" => ["b" => ["c" => 2]]];
$c = array_merge_recursive($a, $b);
那么$c将是:
Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [c] => Array
                        (
                            [0] => 1
                            [1] => 2
                        )

                )

        )

)


drupal实现的合并
drupal中实现了一种特殊的合并,和以上所有合并都不一样,代码位于
Drupal\Component\Utility\NestedArray::mergeDeep($arr1, $arr2, ...);
Drupal\Component\Utility\NestedArray:: mergeDeepArray(array $arrays, $preserve_integer_keys = FALSE)
以上第一个是第二个的特殊情况,仅讲第二个,代码如下:

 

public static function mergeDeepArray(array $arrays, $preserve_integer_keys = FALSE) {
    $result = array();
    foreach ($arrays as $array) {
      foreach ($array as $key => $value) {
        if (is_integer($key) && !$preserve_integer_keys) {
          $result[] = $value;
        }
        elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
          $result[$key] = self::mergeDeepArray(array($result[$key], $value), $preserve_integer_keys);
        }
        else {
          $result[$key] = $value;
        }
      }
    }
    return $result;
  }


它和php的array_merge_recursive函数类似,但又有区别,相似点是都是递归合并,不同点是可以指定参数,且对值有判断。
参数:$preserve_integer_keys指定了对数字索引具备的行为,默认为false,此时数字索引不会前或后覆盖,而是全部保留,并重新索引,和array_merge及array_merge_recursive函数行为一样,如果指定为TRUE,那么将数字索引完全等同于非数字索引。
非数字索引的处理体现了和array_merge_recursive函数的区别:
drupal实现是:相同键名间他们的值都为数组,则进行递归合并,否则只要有一个不是数组,将用后面的值覆盖前面的值。
如:

 

$a = ["a" => 1,"a"];
$b = ["a" => 4,"b"];
$c = array_merge_recursive($a, $b);的结果是:
Array
(
    [a] => Array
        (
            [0] => 1
            [1] => 4
        )

    [0] => a
    [1] => b
)
$c = NestedArray::mergeDeepArray([$a, $b],false);的结果是:
Array
(
    [a] => 4
    [0] => a
    [1] => b
)
$c = NestedArray::mergeDeepArray([$a, $b],true);的结果是:
Array
(
    [a] => 4
    [0] => b
)
当值为数组时,行为如下:
$a = ["a" => [1,2],"a"];
$b = ["a" => [3,4],"b"];

$c = array_merge_recursive($a, $b);时:
Array
(
    [a] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
        )

    [0] => a
    [1] => b
)
$c = NestedArray::mergeDeepArray([$a, $b],false);时和array_merge_recursive输出一致:
Array
(
    [a] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
        )

    [0] => a
    [1] => b
)

$c = NestedArray::mergeDeepArray([$a, $b],true);时
Array
(
    [a] => Array
        (
            [0] => 3
            [1] => 4
        )

    [0] => b
)

 

 

 

我是云客,【云游天下,做客四方】,联系方式见主页,欢迎转载,但须注明出处

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值