Reputation: 18295
$list
is a very large array with a series of words, some of which are greater than 5 characters and some of which are smaller. This loop will unset all values where the length of the word is longer than 5 chars.
for($i = 0; $i < count($list); $i++)
{
$list[$i] = trim($list[$i]);
if(strlen($list[$i]) > 5)
{
unset($list[$i]);
}
}
However, it does that for about half of $list and cuts out dead, there's words which are significantly longer than 5 letters still left in the list, but only starting approximately halfway through. What makes it quit? Should I run that loop multiple times?
Upvotes: 2
Views: 228
Reputation: 20337
The count() is the problem. As a solution, I'm partial to foreach loops.
foreach ($list as $k => $v) {
$list[$k] = trim($v);
if (strlen($list[$k]) < 5) {
unset($list[$k]);
}
}
I think they offer a bit better clarity than the array_ functions.
Upvotes: 1
Reputation: 88697
As you unset()
elements, count()
decreases. This means that what you have describe is very likely to happen. You would be better calling count()
once before the loop, storing it in a variable, and evaluating that at the top of the loop.
Upvotes: 0
Reputation: 179256
It fails because you're incrementing i
while shrinking the total length of the array, which means at some point i
is longer than the current array length.
A safer way of doing this is to count backwards:
for ( $i = count($list); $i--; )
{
$list[$i] = trim($list[$i]);
if(strlen($list[$i]) > 5)
{
unset($list[$i]);
}
}
Upvotes: 5
Reputation: 3838
Every time unset() is called the length of the array changes. Just store it in a variable before the loop:
$count = count($list);
for($i = 0; $i < $count; $i++)
{
// your code
}
Upvotes: 0
Reputation: 408
Works amazingly fast in my netbook's poor hardware with a 10000 list of words from www.lipsum.com
function max_len_filter($var) {
if(strlen($var) > 5) return false;
return true;
}
$words = array_filter($words, 'max_len_filter');
var_dump($words);
Hope it works for you
Upvotes: 0
Reputation: 8003
You're calling count every time, and you're unsetting things during the loop. Call count only once, before the loop. This is good practice to do anyways, as it greatly reduces the number of function calls you have to make.
$count = count($list);
for($i = 0; $i < $count; $i++)
{
$list[$i] = trim($list[$i]);
if(strlen($list[$i]) > 5)
{
unset($list[$i]);
}
}
Or just for fun, use array_map/array_filter:
$list = array_map('trim', $list);
$list = array_filter($list, function($s) { return strlen($s) <= 5; });
Upvotes: 7
Reputation: 1461
You need to loop through from count($list) down to 0; when you remove starting at the beginning, you actually have fewer items by the time you get to the end.
It would also be useful to store count($list) before the loop instead of evaluating it each time.
Upvotes: 0
Reputation: 1322
Count($list) is changing as you unset $list elements so every iteration count returns a smaller value.
Upvotes: 2