php 从数组中选择每第 n 个项目
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1939581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Selecting every nth item from an array
提问by Tatu Ulmanen
What would be the most efficientway to select every nth item from a large array? Is there a 'smart' way to do it or is looping the only way?
从大数组中选择第 n 个项目的最有效方法是什么?有没有一种“聪明”的方法来做到这一点还是循环的唯一方法?
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
- 该数组非常大,包含 130 000 个项目
- 我必须选择每 205 个项目
- 这些项目没有数字索引,所以
for($i = 0; $i <= 130000; $i += 205)不起作用
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!
周围都有正确的解释的好答案,试图选择最合适的作为公认的答案。谢谢!
采纳答案by Corey Ballou
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.
基于比较测试,foreach 循环提供了对大型数组的最快迭代。除非有人希望通过循环展开来解决问题,否则我会坚持使用类似于您所拥有的东西。
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:
我没有时间进行测试,但是如果您首先对数组进行数字索引,您可能可以使用@haim 解决方案的变体。值得尝试看看您是否可以从我以前的解决方案中获得任何收益:
$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.
这在很大程度上取决于函数 array_values 的优化程度。它可能表现得非常糟糕。
回答by Gordon
Also, using one the new Spl datastructuresmight yield better results than using plain arrays.
此外,使用一种新的Spl 数据结构可能会产生比使用普通数组更好的结果。
回答by Haim Evgi
I recommend to using array_slice
我建议使用 array_slice
$count = count($array) ;
for($i=205;$i<$count;$i+=205){
$result[] = array_slice($array,$i,1);
}
If your array was numerically indexed, this would be very fast:
如果您的数组是数字索引的,这将非常快:
$count = count($array) ;
for($i=205;$i<$count;$i+=205){
$result[] = $array[$i];
}
回答by Carson Myers
I think the solution to this problem doesn't lie in any PHP syntax but in the design of your code.
我认为这个问题的解决方案不在于任何 PHP 语法,而在于您的代码设计。
You could either make the array numerically indexed (might not be plausible for your application), keep track of every 205th item, or only search the array once (cache a list of each 205th item).
您可以对数组进行数字索引(可能不适合您的应用程序),跟踪每第 205 个项目,或者只搜索数组一次(缓存每个第 205 个项目的列表)。
In my mind, keeping track of each 205th item would be easier to implement. You'd just keep a count of all the items in a database or something, and every time an item is added, check the modulo of the count. If you have another 205th item, add it to the array. For when items are deleted though, this would be trickier. You might have to re-check the entire array to realign all your 205th items.
在我看来,跟踪第 205 个项目会更容易实现。您只需保留数据库中所有项目的计数或其他内容,每次添加项目时,检查计数的模数。如果您还有第 205 个项目,请将其添加到数组中。但是,当项目被删除时,这会更棘手。您可能需要重新检查整个数组以重新对齐所有第 205 个项目。
Doing this would be simpler if you could start at the deleted item and move forward, but again this would only work for numerically indexed arrays -- and if that were true, you wouldn't have to move forward at all, you would just do a little maths to re-figure it out.
如果您可以从已删除的项目开始并向前移动,这样做会更简单,但这同样仅适用于数字索引数组——如果这是真的,您根本不必向前移动,您只需这样做一些数学来重新弄清楚。
- Numerical indexes -- better long-term solution but harder to implement
- Keeping track -- easier to implement, but you'd have to get dirty again when you delete items
- Caching items -- you should probably do this for the other two solutions as well, but on its own, it would be fast until the array were modified, in which case you would probably have to re-do it.
- 数字索引——更好的长期解决方案但更难实现
- 跟踪——更容易实现,但是当你删除项目时你必须再次变脏
- 缓存项目 - 您可能也应该为其他两个解决方案执行此操作,但就其本身而言,在修改数组之前它会很快,在这种情况下您可能不得不重新执行此操作。
回答by Jonatan Hedborg
If this really is a bottleneck, you might want to consider rethinking your design in order to make it numerically indexed.
如果这确实是一个瓶颈,您可能需要考虑重新考虑您的设计,以便对其进行数字索引。
EDIT: Or create and maintain a seperate array with just the 205th items (which gets updated at insert or something like that).
编辑:或者创建和维护一个单独的数组,其中只有第 205 个项目(在插入时更新或类似的东西)。
回答by Gausie
You can't move the array pointer, it seems, more than once at a time. I would personally use this:
您似乎不能一次多次移动数组指针。我个人会使用这个:
reset($source);
$next = true;
while($next === true){
$result[] = current($source);
for(i=0;i<205;i++){
$next = next($source);
}
}
If someone can find a function that can move the array pointer more than just one step at a time, you will have a better answer. I think this is good though.
如果有人能找到一个函数,可以一次移动数组指针不止一步,那么你会有更好的答案。不过我觉得这很好。
回答by Square Rig Master
- Create a two dimentional array [205][N]
- Load data into array
- Access 205th element for every N
- 创建二维数组 [205][N]
- 将数据加载到数组中
- 每 N 访问第 205 个元素
May sound silly but by definition it is fastest since you access memory locations directly and do not perform any comparisons.
听起来可能很傻,但根据定义,它是最快的,因为您直接访问内存位置并且不执行任何比较。
回答by Gumbo
You could use array_keysto work only on the array keys.
您可以使用array_keys仅在数组键上工作。
$keys = array_keys($array);
for ($i=0, $n=min(count($keys), 130000); $i<$n; $i += 205) {
$result[] = $array[$keys[$i]];
}

