【问题标题】:Foreach with reference causing array's last element to repeatForeach 引用导致数组的最后一个元素重复
【发布时间】:2022-01-13 04:19:59
【问题描述】:

我遇到了一个奇怪的问题,可以用这个 sn-p 重现它:

<?php

$arr = [];

for($i = 0; $i <= 3; $i++) {
    $arr[] = [
        $i
    ];
}

foreach ($arr as &$item) {
    $item[] = $item[0];
}

foreach ($arr as $item) {
    print_r($item);
}

它正在输出(注意最后一个元素已被其前一个元素的副本替换):

Array
(
    [0] => 0
    [1] => 0
)
Array
(
    [0] => 1
    [1] => 1
)
Array
(
    [0] => 2
    [1] => 2
)
Array
(
    [0] => 2
    [1] => 2
)

但是,这是预期的结果:

Array
(
    [0] => 0
    [1] => 0
)
Array
(
    [0] => 1
    [1] => 1
)
Array
(
    [0] => 2
    [1] => 2
)
Array
(
    [0] => 3
    [1] => 3
)

如果我使用array_map 而不是第一个foreach,它可以工作:

<?php

$arr = [];

for($i = 0; $i <= 3; $i++) {
    $arr[] = [
        $i
    ];
}

$arr = array_map(function ($item) {
    $item[] = $item[0];
    return $item;
}, $arr);

foreach ($arr as $item) {
    print_r($item);
}

在 PHP 8.0.0 下测试。

什么可能导致这种差异?我缺少关于数组指针的东西吗?

【问题讨论】:

    标签: php arrays loops foreach


    【解决方案1】:

    在您的第一个示例中,当循环完成时,$item 变量仍然持有对$arr 的最后一个值的引用

    foreach ($arr as &$item) {
        $item[] = $item[0];
    }
    

    如果你使用print_r(get_defined_vars());,你可以看到数组中有一个名为item的键

    foreach结束时double值的行为是described here,建议使用unset($item)销毁指定变量

    您也可以使用不同的变量名。


    使用array_map,回调获取一个按名称传递的函数参数,该参数绑定到函数作用域。

    如果你在使用array_map之后运行print_r(get_defined_vars());,你可以看到没有名为item的键

    【讨论】:

    • 有趣...确实在第二个 foreach 中使用除 $item 之外的其他变量名删除了结尾的欺骗...第一个 foreach 的最终迭代将 $item 标记为对数组最后一个的引用项,而第二个 foreach 语句一遍又一遍地重新分配它(因为它是引用,所以重新分配引用的值),导致最后一项丢失......我理解正确吗?
    • Nvm...确实有一个巨大的红色框警告我在链接文档中所面临的行为。受covid影响的编码有其缺点...感谢您的所有回复!
    【解决方案2】:
    $arr = [];
    
    for($i = 0; $i <= 3; $i++) {
        $arr[] = [
            $i
        ];
    } 
    /** Output 
    * $arr = [[0],[1],[2],[3]]
    */
    

    在这个 foreach 循环中,您只是选择项目的现有值并将其设置为引用项目的新索引

    foreach ($arr as &$item) {
        $item[] = $item[0];
    }
    

    $item 的类型是数组,$item[0] 是指它的 0 索引 $item[] 表示当前引用的 item 内的新数组索引。

    【讨论】:

    • 这是故意的。我只是不明白为什么最后一个元素是[2,2] 而不是[3,3]...
    猜你喜欢
    • 2017-04-08
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多