Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 为什么数组\u merge\u是递归的而不是递归的?_Php_Arrays_Recursion_Array Merge - Fatal编程技术网

Php 为什么数组\u merge\u是递归的而不是递归的?

Php 为什么数组\u merge\u是递归的而不是递归的?,php,arrays,recursion,array-merge,Php,Arrays,Recursion,Array Merge,我最近在我的应用程序中发现了一个bug,它是由数组\u合并\u递归的意外行为引起的。让我们来看看这个简单的例子: $array1 = [ 1 => [ 1 => 100, 2 => 200, ], 2 => [ 3 => 1000, ], 3 => [ 1 => 500 ] ]; $array2 = [ 3 => [

我最近在我的应用程序中发现了一个bug,它是由
数组\u合并\u递归的意外行为引起的。让我们来看看这个简单的例子:

$array1 = [
    1 => [
        1 => 100,
        2 => 200,
    ],
    2 => [
        3 => 1000,
    ],
    3 => [
        1 => 500
    ]
];
$array2 = [
    3 => [
        1 => 500
    ]
];
array_merge_recursive($array1, $array2);
//returns: array:4 [ 0 => //...
我希望得到一个包含3个元素的数组:键1、2和3。但是,该函数返回一个包含键0、1、2和3的数组。所以有4个元素,而我只希望有3个。当我用它们的字母等价物(a、b、c)替换数字时,它返回一个只有3个元素的数组:a、b和c

$array1 = [
    'a' => [
        1 => 100,
        2 => 200,
    ],
    'b' => [
        3 => 1000,
    ],
    'c' => [
        1 => 500
    ]
];
$array2 = [
    'c' => [
        1 => 500
    ]
];
array_merge_recursive($array1, $array2);
//returns: array:3 [ 'a' => //...
这(至少对我来说)是意外的行为,但至少有文件证明:

如果输入数组具有相同的字符串键,则 这些键被合并到一个数组中,这就完成了 递归地,因此如果其中一个值是数组本身,则 函数将它与另一个数组中的对应项合并 也但是,如果数组具有相同的数字键,则后面的 值不会覆盖原始值,但将被追加

文档对“附加”的含义不是很清楚。原来带有数字键的
$array1
元素将被视为索引元素,因此它们将丢失当前键:返回的数组以0开头。当在数组中同时使用数字键和字符串键时,这将导致奇怪的结果,但如果您使用的是这样一种糟糕的做法,我们不要责怪PHP。在我的例子中,问题是通过使用
array\u replace\u recursive
解决的,这达到了预期的效果。(“replace”在该函数中表示replace,如果存在,则附加;命名函数很难!)

问题1:递归还是非递归? 但这并不是问题的结束。我认为
array\u*\ u resursive
将是一个递归函数:

递归是函数调用自身的一种函数调用。 这种函数也称为递归函数。结构的 递归是一种解决问题的方法,其中 问题取决于同一问题的较小实例的解决方案

事实证明并非如此。虽然上述示例中的
$array1
$array2
是关联数组,但
$array1['c']
$array2['c']
都是带有一个元素的索引数组:
[1=>500]
。让我们合并它们:

array_merge_recursive($array1['c'], $array2['c']);
//output: array:2 [0 => 500, 1 => 500]
这是预期的输出,因为两个数组都有一个数字键(
1
),所以第二个数组将附加到第一个数组。新数组以键0开头。但让我们回到第一个例子:

array_merge_recursive($array1, $array2);
// output:
// array:3 [
//  "a" => array:2 [
//    1 => 100
//    2 => 200
//  ]
//  "b" => array:1 [
//    3 => 1000
//  ]
//  "c" => array:2 [
//    1 => 500 //<-- why not 0 => 500?
//    2 => 500
//  ]
//]
因此,使用字符串键将
(int)500
强制转换为
数组(500)
,而使用整数键则不会


有人能解释一下这种行为吗?

你应该阅读你提供的链接,它指出(我的重点):

如果输入数组具有相同的字符串键,则这些键的值将合并到一个数组中,并且这是递归进行的,因此如果其中一个值是数组本身,函数也会将其与另一个数组中的相应项合并但是,如果数组具有相同的数字键,则后面的值将不会覆盖原始值,但将被追加


如果我们退后一步,观察
array\u merge*()
函数在一个数组中的行为,那么我们就可以了解它是如何区别对待关联数组和索引数组的:

$array1 = [
    'k' => [
        1 => 100,
        2 => 200,
    ],
    2 => [
        3 => 1000,
    ],
    'f' => 'gf',
    3 => [
        1 => 500
    ],
    '99' => 'hi',
    5 => 'g'
];

var_dump( array_merge_recursive( $array1 ) );
输出:

array(6) {
  ["k"]=>
  array(2) {
    [1]=>
    int(100)
    [2]=>
    int(200)
  }
  [0]=>
  array(1) {
    [3]=>
    int(1000)
  }
  ["f"]=>
  string(2) "gf"
  [1]=>
  array(1) {
    [1]=>
    int(500)
  }
  [2]=>
  string(2) "hi"
  [3]=>
  string(1) "g"
}
如您所见,它使用了所有数字键,忽略了它们的实际值,并按照遇到它们的顺序将它们返回给您。我认为函数这样做是为了在底层C代码中保持健全(或效率)

回到您的两个数组示例,它获取
$array1
的值,对它们进行排序,然后添加
$array2


这个行为是否正常是一个完全独立的讨论…

-PHP数组和所有与之相连的函数都是香蕉…这并不能解释为什么用数字键合并两个数组会导致一个以0开头的数组,但如果其中一个值是数组本身,原始元素将保留它的键。我否决了你的答案,因为它没有回答问题。我在问题中引用了完全相同的话,强调了几乎相同的词。@StephanVierkant,那么你应该把你的问题和投诉交给维护PHP的小组
array\u merge\u recursive
是PHP语言的一部分。因此,质疑PHP的维护者如何实现该语言的论坛是错误的。你是对的,这是实际的行为。但是为什么
$array
的(数字)键的实际值被忽略,而
$array['k']
$array[1]
的(也是数字)键没有被忽略?这样听起来不是递归的。@StephanVierkant你是对的,那些子数组理论上应该重新编号……还是主数组不应该重新编号?@StephanVierkant PHP 7似乎真的把
数组\u merge\u recursive()
搞砸了。我提交了一份bug报告;看见
array(6) {
  ["k"]=>
  array(2) {
    [1]=>
    int(100)
    [2]=>
    int(200)
  }
  [0]=>
  array(1) {
    [3]=>
    int(1000)
  }
  ["f"]=>
  string(2) "gf"
  [1]=>
  array(1) {
    [1]=>
    int(500)
  }
  [2]=>
  string(2) "hi"
  [3]=>
  string(1) "g"
}