25. 常见操作数组合并

合并数组

drupal8的源码实现中有非常多的合并数组操作,这本是php层面的知识,但鉴于用的如此之多,而且drupal还专门实现了一种合并方法,所以特别设置一个主题来讲解。

合并php数组主要有以下几个方法:

1:通过“+”操作符号进行数组相加的前保留合并

2:函数:array_merge 后保留合并

3array_merge_recursive 递归且全保留合并

4drupal实现的条件式合并

 

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

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

$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;
  }

它和phparray_merge_recursive函数类似,但又有区别,相似点是都是递归合并,不同点是可以指定参数,且对值有判断。

参数:$preserve_integer_keys指定了对数字索引具备的行为,默认为false,此时数字索引不会前或后覆盖,而是全部保留,并重新索引,和array_mergearray_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
)

 

 

添加新评论

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。
请输入以上问题的答案,换一个问题请刷新,不区分大小写