【问题标题】:PHP foreeach deleting array elementPHP foreach 删除数组元素
【发布时间】:2012-12-27 03:18:02
【问题描述】:

今天在开发用于博客的文本分析工具时,我发现 PHP 的行为对我来说非常奇怪,我无法理解它。在规范化文本时,我试图删除最小长度以下的单词,所以我在规范化方法中写了这个:

if ($this->minimumLength > 1) {
    foreach ($string as &$word)
    {
        if (strlen($word) < $this->minimumLength) {
            unset($word);
        }
    }
}

奇怪的是,这会在我的数组中留下一些低于允许长度的单词。在全班搜索错误后,我试了一下:

if ($this->minimumLength > 1) {
        foreach ($string as $key => $word)
        {
            if (strlen($word) < $this->minimumLength) {
                unset($string[$key]);
            }
        }
    }

瞧!这非常有效。现在,为什么会发生这种情况?我查看了PHP Documentation 并指出:

如果通过引用传递的变量在函数内部是 unset(),则只有局部变量被销毁。调用环境中的变量将保持与调用 unset() 之前相同的值。

foreach 是否在这里充当calling environment,因为它有自己的范围?

【问题讨论】:

  • 永远不要修改你正在迭代的东西,因为这种意外行为。
  • 没有回答你关于引用的问题,但最简单、最干净的方法是使用 array_filter() 函数 - php.net/manual/en/function.array-filter.php
  • 谢谢你,我之前使用过array_filter,但用于一些不同的目的。对于从数组中删除元素这样“简单”的操作,我不会想到它,但似乎将它们设置为 false 并在其上运行 array_filter 确实是最清晰的方法

标签: php foreach unset


【解决方案1】:

不,这里没有函数调用,也没有通过引用传递变量(您只是在迭代期间通过引用捕获)。

当您通过引用进行迭代时,迭代变量是原始变量的别名。当您使用此别名引用原始别名并修改其值时,更改将在被迭代的数组中保持可见。

但是,当您unset 别名时,原始变量并未“销毁”; alias 只是从符号表中删除。

foreach ($string as $key => &$word)
{
    // This does not mean that the word is removed from $string
    unset($word);

    // It simply means that you cannot refer to the iteration variable using
    // $word from this point on. If you have captured the key then you can
    // still refer to it with $string[$key]; otherwise, you have lost all handles
    // to it for the remainder of the loop body
}

【讨论】:

  • 哦....不知何故,我一直认为所有针对值引用的操作都会反映到值本身上。我想我错了,谢谢你澄清这个问题。
  • @igorpan:一个相关的提示是,当您使用引用进行迭代时,您可能希望在循环体之后立即unset 循环变量;否则,您“冒险”分配给该变量,这将覆盖迭代中的最后一个值。
  • 我知道,即使在循环本身结束后,循环变量也会保持定义。不过,如果有人偶然发现这个问题,它会很有用:)
【解决方案2】:

当您在 if 语句中调用 unset($word) 时,您正在删除 $word 变量本身,而不对数组 $string 进行任何更改。

【讨论】:

  • 但是当我通过引用传递它时,为什么会这样呢?我的 foreach 状态 foreach ($string as &amp;$word)
  • 因为它是对原始变量的引用,而不是实际的原始变量;您再次取消设置参考,但原始仍然存在
猜你喜欢
  • 2012-02-15
  • 2015-02-13
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
相关资源
最近更新 更多