0

Imagine a simple, but large array with keys 0 to 100000.

When doing a foreach loop of this array, is it possible to 'seek' ahead without doing something like:

foreach($array as $key=>$value){
    if($key<10000){
         continue;
    }
}

We do this kind of operation once in a while thru our codebase. It seams like a bit of a waste of ticks to go thru each of the keys until key is greater then 10000.

Is this possible in php 5.4?

Thanks.

anonymous-one
  • 14,454
  • 18
  • 60
  • 84

4 Answers4

5

it was possible even in PHP 2.0FI or ALTAIR BASIC

for($i=10000;$i < count($array);$i++){
}

No doubt some nitpickers will come to tell that doing count($array) 90000 times is a waste of ticks too. However, to get a real performance gain one have to avoid lengthy loops at all.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 5
    this would work, i would further expand this by variabalizing count prior to the foreach so that count is not executed on each loop. – anonymous-one Mar 09 '12 at 08:02
  • this is the method we will begin using from this point forward. although i must note both (at the time of this writing) answers below were excellent. thanks. – anonymous-one Mar 09 '12 at 08:05
  • Couldn't performance gain be considered getting rid of non essential operations? The loop may be unquestionably essential in some situation, however, 90000 calls to count is not. (And yes, I suppose this makes me the nitpicker :) ) – Corbin Mar 09 '12 at 08:17
  • @Corbin So I say - get rid of unessential lengthy loop. – Your Common Sense Mar 09 '12 at 08:23
  • But what I'm saying is, the loop might be necessary in some weird situation. The continued count however, is not. But eh, you're right that in the big scheme of things, the count calls are going to be negligible compared to the giant loop. – Corbin Mar 09 '12 at 08:24
  • @Corbin For the web development it cannot be essential but quite contrary - such a loop sholdn't be used on a regular basis at all. For the one-shot action it doesn't matter at all. With this conversation you already wasted a lot more ticks than you can save counting arrays :) – Your Common Sense Mar 09 '12 at 08:32
  • Ah I didn't think about the context of the loop. Got me. – Corbin Mar 09 '12 at 08:34
3
$rest = array_slice($array, 10000);

Depending on what you want to achieve (here: what you want to do after seeking)

for ($length = count($array), $key = 10000; $key < $length, $key++) {
  $value = $array[$key];
}
KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • i like this answer the best so far. i will do some benchmarking and see how much weight doing an array_slice vs X number of if ( key ... continue; adds. – anonymous-one Mar 09 '12 at 08:03
  • 1
    Seems like array slice would be inefficient for this. Unless PHP's copy-on-write system is way more advanced than I think it is, that would copy quite a few elements unneccessarily. – Corbin Mar 09 '12 at 08:03
  • @Corbin I agree, but at all this hardly depends on how the array looks like, what the OP wants to do with the array(s) later, and much more things. If the OP doesn't need the first `X` elements anymore, there seems to be no good reason to keep them. – KingCrunch Mar 09 '12 at 08:11
  • @KingCrunch But, that also doesn't mean that there's a reason to copy them. Why copy if it's not necessary? To free up the memory? Well, it's a copy. (Though I guess you could put an unset call after it.) – Corbin Mar 09 '12 at 08:13
  • @Corbin I only can repeat myself: What is better, or worse, is just a matter of what should happens next. It's not even said, that this code snippet appears in a web application, but in a cli tool ^^ For example `$chunks = array_chunk($array, 10000);` could be a solution too. – KingCrunch Mar 09 '12 at 08:30
1

Assuming the keys are consecutive integers:

$count = count($array);
for ($key = 10000; $key < $count; ++$key) {
    $value = $array[$key];
}

I'm not sure if count is O(1) though, so if it's not, you might be better off doing:

$key = 0;
while (isset($array[$key])) {
    $value = $array[$key];
    ++$key;
}

Note that array_key_exists would be required if the key could be considered not set yet exist in the array.

Corbin
  • 33,060
  • 6
  • 68
  • 78
  • I think so since there's the $arr[] = blah syntax. That statement would be O(n) otherwise, and that would have horrid performance implications. Now that I think about it, it must be O(1), definitely for numeric keys anyway. – Corbin Mar 09 '12 at 08:04
  • 1
    See [PHP's count(), O(1) or O(n) for arrays?](http://stackoverflow.com/questions/5835241/phps-count-o1-or-on-for-arrays) – BoltClock Mar 09 '12 at 08:04
  • Ah, as suspected. I should have not been lazy and searched it myself :). Thanks. – Corbin Mar 09 '12 at 08:05
0

Borrowing from this solution, this would do the trick and set the array pointer at the element you want. This would be the closest you get to seeking the array and not just specifying the interval of keys to loop through.

$start = 10000; // or what ever number you're starting at
while(key($array) < $start) next($array);

You can't use this if you plan to use a foreach-loop (as it resets the pointer), but should be good if you iterate the rest of the array like this

$count = count($array);
do {
  $key = key($array);
  $value = current($array);
} while($key < $count);
Community
  • 1
  • 1
Flygenring
  • 3,818
  • 1
  • 32
  • 39
  • Erm... Isn't that just non-standard syntax for the non-optimal solution he already mentioned in his question? – Corbin Mar 09 '12 at 08:22
  • It's not that non-standard, and as it has less operations it should be a more efficient way of seeking. I gave the solution because I wanted to show that you don't need to use for-loops for this kind of task and answer the question as precisely as I saw possible, not to say it's the best or most efficient solution to this particular problem. – Flygenring Mar 09 '12 at 08:29
  • At the low level, I am fairly certain it would be more operations. You're right though that it does literally seek. And it is a different solution. – Corbin Mar 09 '12 at 08:36
  • Well, I'm not sure but I don't have the time to do any benchmarking right now. Anyhow, I just wanted to diversify the world a little and I'm glad you commented, as I forgot to clarify that it wasn't the optimal way to loop a certain part of an array. – Flygenring Mar 09 '12 at 08:42