Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting every nth item from an array

Tags:

arrays

php

What would be the most efficient way to select every nth item from a large array? Is there a 'smart' way to do it or is looping the only way?

Some points to consider:

  • The array is quite large with 130 000 items
  • I have to select every 205th item
  • The items are not numerically indexed, so for($i = 0; $i <= 130000; $i += 205) won't work

So far, this is the most efficient method I've come up with:

$result = array();
$i = 0;
foreach($source as $value) {

    if($i >= 205) {
        $i = 0;
    }

    if($i == 0) {
        $result[] = $value;
    }

    $i++;
}

Or the same with modulo:

$result = array();
$i = 0;
foreach($source as $value) {
    if($i % 205 == 0) {
        $result[] = $value;
    }
    $i++;
}

These methods can be quite slow, is there any way to improve? Or am I just splitting hairs here?

EDIT

Good answers all around with proper explanations, tried to pick the most fitting as the accepted answer. Thanks!

like image 295
Tatu Ulmanen Avatar asked Dec 21 '09 11:12

Tatu Ulmanen


2 Answers

A foreach loop provides the fastest iteration over your large array based on comparison testing. I'd stick with something similar to what you have unless somebody wishes to solve the problem with loop unrolling.

This answer should run quicker.

$result = array();
$i = 0;
foreach($source as $value) {
    if ($i++ % 205 == 0) {
        $result[] = $value;
    }
}

I don't have time to test, but you might be able to use a variation of @haim's solution if you first numerically index the array. It's worth trying to see if you can receive any gains over my previous solution:

$result = array();
$source = array_values($source);
$count = count($source);
for($i = 0; $i < $count; $i += 205) {
    $result[] = $source[$i];
}

This would largely depend on how optimized the function array_values is. It could very well perform horribly.

like image 108
Corey Ballou Avatar answered Oct 18 '22 13:10

Corey Ballou


Try ArrayIterator::seek()

Also, using one the new Spl datastructures might yield better results than using plain arrays.

like image 42
Gordon Avatar answered Oct 18 '22 11:10

Gordon