为什么这个循环会中途放弃?

时间:2011-09-01 22:08:53

标签: php

$list是一个非常大的数组,包含一系列单词,其中一些大于5个字符,其中一些字符较小。此循环将取消设置字长超过5个字符的所有值。

for($i = 0; $i < count($list); $i++)
{
    $list[$i] = trim($list[$i]);
    if(strlen($list[$i]) > 5)
    {
        unset($list[$i]);
    }
}

然而,这对于大约一半的$ list并且已经删除了死亡,这些单词比列表中剩下的5个字母长得多,但只是大约一半开始。是什么让它退出?我应该多次运行该循环吗?

8 个答案:

答案 0 :(得分:7)

你每次都在呼唤计数,而你在循环中就是在取消东西。在循环之前只调用一次计数。无论如何这都是很好的做法,因为它大大减少了你必须进行的函数调用次数。

$count = count($list);
for($i = 0; $i < $count; $i++)
{
    $list[$i] = trim($list[$i]);
    if(strlen($list[$i]) > 5)
    {
        unset($list[$i]);
    }
}

或者只是为了好玩,请使用array_map / array_filter:

$list = array_map('trim', $list);
$list = array_filter($list, function($s) { return strlen($s) <= 5; });

答案 1 :(得分:5)

它失败是因为你在缩小数组总长度的同时递增i,这意味着在某些时候i比当前数组长度更长。

更安全的做法是向后倒数:

for ( $i = count($list); $i--; )
{
    $list[$i] = trim($list[$i]);
    if(strlen($list[$i]) > 5)
    {
        unset($list[$i]);
    }
}

答案 2 :(得分:2)

计数($ list)在取消设置$ list元素时发生变化,因此每次迭代计数都会返回一个较小的值。

答案 3 :(得分:1)

count()是问题所在。作为一个解决方案,我偏向于循环。

foreach ($list as $k => $v) {
    $list[$k] = trim($v);

    if (strlen($list[$k]) < 5) {
        unset($list[$k]);
    }
}

我认为它们比array_函数提供更好的清晰度。

答案 4 :(得分:0)

你需要从count($ list)循环到0;当你从头开始删除时,到实际结束时你实际上有更少的项目。

在循环之前存储count($ list)而不是每次都进行评估也很有用。

答案 5 :(得分:0)

当您unset()元素时,count()会减少。这意味着您所描述的内容很可能会发生。你最好在循环之前调用count()一次,将它存储在一个变量中,然后在循环的顶部进行评估。

答案 6 :(得分:0)

在我的上网本糟糕的硬件上工作得非常快,有来自www.lipsum.com的10000个单词列表

function max_len_filter($var) {
    if(strlen($var) > 5) return false;
    return true;
}
$words = array_filter($words, 'max_len_filter');
var_dump($words);

希望它适合你

答案 7 :(得分:0)

每次调用unset()时,数组的长度都会发生变化。 只需将它存储在循环之前的变量中:

$count = count($list);
for($i = 0; $i < $count; $i++)
{
   // your code
}