从数组中选择每个第n项

时间:2009-12-21 11:30:08

标签: php arrays

从大型数组中选择每个第n项的最高效方法是什么?是否有“聪明”的方式来做或者循环唯一的方式?

需要考虑的一些要点:

  • 数组相当大,有130 000个项目
  • 我必须选择每第205个项目
  • 这些项目未按数字编入索引,因此for($i = 0; $i <= 130000; $i += 205)无效

到目前为止,这是我提出的最有效的方法:

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

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

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

    $i++;
}

或与模数相同:

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

这些方法可能很慢,有什么办法可以改进吗?或者我只是在这里分裂头发?

修改

通过正确的解释得到了很好的答案,试图选择最合适的答案。谢谢!

8 个答案:

答案 0 :(得分:15)

foreach循环基于比较测试为您的大型阵列提供最快的迭代。除非有人希望通过循环展开解决问题,否则我会坚持使用类似于你的东西。

这个答案应该更快。

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

我没有时间进行测试,但如果您首先对数组进行数字索引,则可以使用@ haim解决方案的变体。值得一试的是,您是否可以获得比我以前的解决方案更多的收益:

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

这在很大程度上取决于函数array_values的优化程度。它可能会表现得非常糟糕。

答案 1 :(得分:7)

尝试ArrayIterator::seek()

此外,使用新的Spl datastructures可能会产生比使用普通数组更好的结果。

答案 2 :(得分:6)

我建议使用array_slice

$count = count($array) ;
for($i=205;$i<$count;$i+=205){
    $result[] = array_slice($array,$i,1);
}

如果您的数组以数字方式编入索引,则速度非常快:

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

答案 3 :(得分:2)

我认为这个问题的解决方案不在于任何PHP语法,而在于代码的设计。

您可以对数组进行数字索引(对您的应用程序可能不合理),跟踪每个第205项,或只搜索一次数组(缓存每个第205项的列表)。

在我看来,跟踪每个第205项将更容易实现。您只需保留数据库中所有项目的计数,每次添加项目时,请检查计数的模数。如果您有另一个第205项,请将其添加到阵列。对于删除项目时,这将更加棘手。您可能需要重新检查整个阵列以重新排列所有第205个项目。

如果您可以从已删除的项目开始并向前移动,那么这样做会更简单,但这又适用于数字索引的数组 - 如果这是真的,那么您根本不需要前进,我会做一些小数学来重新计算出来。

  • 数字索引 - 更好的长期解决方案,但更难实施
  • 保持跟踪 - 更容易实现,但删除项目时必须再次弄脏
  • 缓存项目 - 您也应该为其他两个解决方案执行此操作,但就其自身而言,在修改数组之前会很快,在这种情况下您可能需要重新执行此操作。

答案 4 :(得分:1)

如果这确实是一个瓶颈,您可能需要考虑重新考虑您的设计,以便对其进行数字索引。

编辑:或者创建并维护一个单独的数组,只包含第205个项目(在插入时更新或类似的更新)。

答案 5 :(得分:0)

您似乎不能一次多次移动数组指针。我个人会用这个:

reset($source);
$next = true;
while($next === true){
    $result[] = current($source);
    for(i=0;i<205;i++){
        $next = next($source);
    }
}

如果某人能够找到一个可以一次移动数组指针的功能,那么你将获得更好的答案。我认为这很好。

答案 6 :(得分:0)

  • 创建一个二维数组[205] [N]
  • 将数据加载到数组
  • 每N
  • 访问第205个元素

可能听起来很傻但是根据定义它是最快的,因为你直接访问内存位置而不进行任何比较。

答案 7 :(得分:-1)

您可以使用array_keys仅对数组键起作用。

$keys = array_keys($array);
for ($i=0, $n=min(count($keys), 130000); $i<$n; $i += 205) {
    $result[] = $array[$keys[$i]];
}