25. 合并数组
在drupal8的源码实现中有非常多的合并数组操作,这本是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=array_merge($a,$b);
那么$c将是["a"=>4,"b"=>2,"c"=>6,"a",d"=>5,"b"];
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)
以上第一个是第二个的特殊情况,仅讲第二个,代码如下:(见辅助内容区)
它和php的array_merge_recursive函数类似,但又有区别,相似点是都是递归合并,不同点是可以指定参数,且对值有判断。
参数:$preserve_integer_keys指定了对数字索引具备的行为,默认为false,此时数字索引不会前或后覆盖,而是全部保留,并重新索引,和array_merge及array_merge_recursive函数行为一样,如果指定为TRUE,那么将数字索引完全等同于非数字索引。
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;
}
非数字索引的处理体现了和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
)