【问题标题】:PHP Callback Functions and Variable ReferencesPHP 回调函数和变量引用
【发布时间】:2016-05-03 18:10:26
【问题描述】:

我正在努力解决 HackerRank 上的“Avery Big Sum”问题。目标是在不使用 array_sum 的情况下生成数组中所有元素的总和。为了清楚起见,这里的示例代码与那里的代码有点不同。

这行得通:

$arr = array( 
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
);

$total = 0;
array_walk($arr, 'totalize');
echo '*' . $total;

function totalize( $arr_item ) {
    global $total;
    $total += $arr_item;
}

我想避免使用全局,以便将来在使用回调函数时可以正确处理。但是,这不起作用。我将在代码之后显示输出:

$arr = array( 
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
);

$total = 0;
array_walk($arr, 'totalize', $total);
echo '*' . $total;

function totalize( $arr_item, $key, &$total ) {
    $total += $arr_item;
    echo $arr_item . '.' . $key . '.' . $total . '<br />';
}

它给出这个作为输出:

1000000001.0.1000000001
1000000002.1.2000000003
1000000003.2.3000000006
1000000004.3.4000000010
1000000005.4.5000000015
*0

为什么 $total 被正确加起来却被放弃了?

答案: 感谢@miken32,我发现这行得通:

$arr = array( 
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
);

$total = 0;
array_walk($arr, function( $arr_item ) use ( &$total ) { totalize( $arr_item, $total ); } );
echo '*' . $total;

function totalize( $arr_item, &$total ) {
    $total += $arr_item;
    echo $arr_item . '.' . $total . '<br />';
}

它给出了这个输出:

1000000001.1000000001
1000000002.2000000003
1000000003.3000000006
1000000004.4000000010
1000000005.5000000015
*5000000015

【问题讨论】:

  • 要么使用匿名函数并使用use(),要么只是执行一个简单的 foreach 循环来遍历您的数组并将值相加。
  • 命名空间有什么关系?我正在尝试学习如何将指针传递给函数,而不仅仅是解决这个问题。
  • 不是use,而是use()对于匿名函数,有区别:)
  • 我在以下答案之一中看到了这一点。很有趣。

标签: php scope reference


【解决方案1】:

对于这种特殊情况,您可以使用 anonymous functionthe use keyword$total 导入函数的作用域。

$arr = [
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
];

$total = 0;
array_walk($arr, function ($arr_item) use (&$total) {$total += $arr_item;});
echo '*' . $total;

【讨论】:

  • 谢谢,我可以让匿名函数通过引用累加器函数。我会显示代码,但它在 cmets 中的格式不正确。那么,如果不使用匿名函数,回调不能通过引用传递,我是否正确?
  • 如果array_walk() 的回调函数被设置为通过引用接受变量,那么它没有理由不起作用。但这就像试图让任何内置函数通过引用接受一个值。如果它不是这样写的,那就行不通了。
【解决方案2】:

array_walk() 的第三个参数不能作为引用传递。当您调用array_walk() 时,它使用您作为第三个参数传递的值来初始化一个局部变量。然后它通过引用你的回调来传递局部变量(因为这是你的回调的定义方式)。

但是在全局变量$total 和传递给你的回调的变量(totalize() 的参数$total)之间没有链接。如果您将totalize() 更改为也显示全局变量$total 的值,您可以自己看到这一点。

达到目标的更合适的方法是使用array_reduce()。文档中的第一个示例正是您的问题的解决方案。

【讨论】:

  • 回调确实传递了一个引用。 PHP 核心在处理回调传递引用的方式上发生了变化。使用:array_walk($arr, 'totalize', &$total);给出错误:致命错误:调用时传递引用已在第 12 行的 /home/quicksil/public_html/test.php 中删除
  • 确实,您不能强制传递全局 $total 作为对 array_walk() 的引用。它复制它收到的值作为第三个参数,它不会更改它。您甚至可以将0 作为第三个参数传递,它仍然会产生相同的结果。
猜你喜欢
  • 2011-01-01
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多