$array1 = [
'1' => '11',
'b' => 1,
3 => 33,
8 => 8
];
$array2 = [
'1' => '22',
'b' => 2,
3 => 44,
9 => 9
];
$merged = array_merge_recursive($array1, $array2);
结果是:
array(7) {
[0]=>
string(2) "11"
["b"]=>
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
[1]=>
int(33)
[2]=>
int(8)
[3]=>
string(2) "22"
[4]=>
int(44)
[5]=>
int(9)
}
所以让我们一目了然:唯一的部分是'b'
键,它们实际上是有效的。我不想覆盖它的任何东西,但把它们放在一个数组中。非常好!但随后键其他数字键(int或string)被搞砸了。
我希望得到这个结果:
[
'1' => ['11', '22']
'b' => [1, 2]
[3] => [33, 44]
[8] => 8,
[9] => 9
]
可能?
编辑:当然键“1”和1 - 字符串与int键是相同的
答案 0 :(得分:2)
让我们将这个问题分解为单独的问题:
说实话,我不知道解决此问题的简便方法。我不确定是否有一个。即使,我不确定您是否真的想要它。这样的函数将导致数组的值是字符串或。您将如何处理这样的数组?
更新:嗯,有一个。您的示例已经显示array_merge_recursive
会将带有字符串键的值转换为数组。因此1 => 'foo'
将是0 => 'foo'
,但是'foo' => 'bar'
最终将变成'foo' => ['bar']
。我真的不明白这种行为。
在这种情况下,使用字符串键可以为您提供帮助,但是在进一步了解array_merge_recursive
之后,我决定尽可能避免使用此功能。在我询问this question之后,有人将其归档为bug in it since PHP 7.0,因为它在PHP 5.x中的工作方式有所不同。
array_merge_resursive
则不保留整数键,而保留整数键:如果输入数组具有相同的 string 键,则用于 这些键被合并在一起成为一个数组,这完成了 递归,因此,如果值之一是数组本身,则 函数将其与另一个数组中的对应条目合并 太。但是,如果数组具有相同的数字键,则后者 值不会覆盖原始值,但会附加。
更糟糕的是,在处理嵌套数组时,其处理方式有所不同:
$array1 = [30 => [500 => 'foo', 600 => 'bar']];
$array2 = [];
array_merge_recursive($array1, $array2);
//[0 => [500=> 'foo', 600 => 'bar']];
实际上,array_merge_resursive
并不是 resursive 。
使用array_replace_resursive解决了这个问题:
array_replace_recursive($array1, $array2);
//output:
//array:5 [
// 1 => "22"
// "b" => 2
// 3 => 44
// 8 => 8
// 9 => 9
//]
请注意,PHP在不一致方面非常一致。虽然array_merge_recursive
不是递归的,但是array_replace_recursive
不会替代(它也会追加):
如果键存在于第二个数组而不是第一个数组中,它将是 在第一个数组中创建。
在许多情况下,这是期望的行为,并且由于命名功能不是PHP的强项,因此您可以将其视为次要问题。
答案 1 :(得分:1)
您能否依靠本机函数来返回您想要的确切输出?不会。至少在本文发布之日的任何版本中都没有(PHP8.1 之前)。
好消息是制定您自己的解决方案非常简单。
代码:(Demo)
foreach ($array2 as $key => $value) {
if (!key_exists($key, $array1)) {
$array1[$key] = $value;
} else {
$array1[$key] = (array)$array1[$key];
$array1[$key][] = $value;
}
}
var_export($array1);
我想我不太倾向于推荐这种输出结构,因为在给定级别上您可能有不同的数据类型。如果您正在构建后续代码来迭代此数据,则需要在每个级别上编写条件以查看数据是否可迭代 - 感觉就像您正在为代码膨胀/卷积做准备。我更喜欢具有一致深度和数据类型的结果。