【问题标题】:Why array_shift on an array with an empty string breaks the loop?为什么 array_shift 在带有空字符串的数组上会中断循环?
【发布时间】:2018-08-19 03:48:39
【问题描述】:

我刚刚注意到,当遇到空字符串时,使用 while 和 array_shift 迭代数组的行为与简单的 for 循环不同。这是一个示例:

While循环:

$arr=[1, "",1,""];
while ($elm = array_shift($arr))
{
    var_dump($elm);
}

for循环:

$arr=[1, "",1,""];
for ($i = 0; $i<count($arr); $i++)
{
    var_dump($arr[$i]);
}
die();

为什么while会退出循环?

【问题讨论】:

  • 因为表达式的计算结果为 false ?
  • 要让while循环继续运行,必须在while()中提供true值。在第一个数组中,您的第二个值是null,它被视为false0 值。因此,while 循环停止。

标签: php loops for-loop while-loop


【解决方案1】:

因为空字符串在 PHP 中是 falsy 值:

var_dump((bool) ""); // bool(false)

The PHP Manual

要使第一个示例使用空字符串,您应该检查 array_shift 返回 NULL

$arr = [1, "", 1, ""];
while (($elm = array_shift($arr)) !== NULL) {
    var_dump($elm);
}

说明

array_shift 从数组中移除第一个元素并返回其值:

$arr = [1, ""];
array_shift($arr); // we get 1
array_shift($arr); // we get ""
array_shift($arr); // we get NULL because the array is empty now

在您的第一个示例中,您有 while ($elm = array_shift($arr)),这意味着:

  • 删除第一个元素并将其值保存在$elm
  • $elm 解释为布尔值(这是隐式完成的),并且仅在其评估结果为 TRUE 时继续。

让我们手动遍历每个迭代以使其更清晰:

  • 第一次迭代:while ($elm = 1) -> while (true) 因为 1 是真实的。 我们继续循环

  • 第二次迭代:while ($elm = "") -> while (false) 因为空字符串是虚假的。 我们退出循环

【讨论】:

  • 为清楚起见,$elm = array_shift($arr) 等价于 $elm = "",由操作中设置的左侧变量值评估,例如,"",其评估结果为 false。
  • 我猜在性能方面,for 循环比 while 加 null 测试要好,对吗?
  • @sabas 绝对是。 array_shift 更改原始数组(这需要额外的时间),for 循环不会:$arr = [1,2,3]; array_shift($arr);array_shift($arr);array_shift($arr); var_dump($arr); 输出一个空数组。
【解决方案2】:

因为空字符串的计算结果为假

【讨论】:

    【解决方案3】:

    因为 数组的第二个值是空字符串,它会转换为 bool false

    尝试使用另一个数组,一切都会好起来的:

    $arr=[1, "non-empty value", 1, "another non-empty value"];
    while ($elm = array_shift($arr))
    {
        var_dump($elm);
        echo '<br>'; // this is bonus ;)
    }
    

    【讨论】:

      【解决方案4】:

      如果数组包含null,其他人提出的解决方案仍然容易出错。如果真的需要修改数组而不是做一个简单的foreach,那么构建它的稳健方法是:

      while ($arr)
      {
          $elm = array_shift($arr)
          var_dump($elm);
      }
      

      这是因为数组总是真实的,除非它们是空的,不管它们包含什么值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-31
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多