如何确定foreach循环中的第一个和最后一个迭代?
问题很简单。 我在我的代码中有一个foreach循环: 
 foreach($array as $element) { //code } 
在这个循环中,当我们在第一次或最后一次迭代时,我想要做出不同的反应。
如何做到这一点?
你可以使用一个计数器:
 $i = 0; $len = count($array); foreach ($array as $item) { if ($i == 0) { // first } else if ($i == $len - 1) { // last } // … $i++; } 
如果你的数组有唯一的数组值,那么确定第一个和最后一个元素是微不足道的:
 foreach($array as $element) { if ($element === reset($array)) echo 'FIRST ELEMENT!'; if ($element === end($array)) echo 'LAST ELEMENT!'; } 
如果最后一个元素和第一个元素只在数组中出现一次,这就可以工作,否则你会得到误报。 因此,你必须比较键(他们是唯一的肯定)。
 foreach($array as $key => $element) { reset($array); if ($key === key($array)) echo 'FIRST ELEMENT!'; end($array); if ($key === key($array)) echo 'LAST ELEMENT!'; } 
更新:有些人担心性能和/或修改foreach循环内的数组指针。 对于这些,你可以在循环之前caching键值。
 reset($array); $first = key($array); foreach($array as $key => $element) { if ($key === $first) echo 'FIRST ELEMENT!'; } 
要find最后一个项目,我发现这段代码每次都有效:
 foreach( $items as $item ) { if( !next( $items ) ) { echo 'Last Item'; } } 
上面的更简化的版本,并假设你不使用自定义索引…
 $len = count($array); foreach ($array as $index => $item) { if ($index == 0) { // first } else if ($index == $len - 1) { // last } } 
 您可以从arrays中删除第一个和最后一个元素,并分别处理它们。 
 喜欢这个: 
 <?php $array = something(); $first = array_shift($array); $last = array_pop($array); // do something with $first foreach ($array as $item) { // do something with $item } // do something with $last ?> 
删除所有的格式,而不是内联标签将改善你的代码和加快加载时间。
 只要有可能,您也可以避免将PHP与逻辑混合在一起。 
 通过分隔这样的东西,可以使您的页面更具可读性和可维护性: 
 <?php function create_menu($params) { //retirive menu items //get collection $collection = get('xxcollection') ; foreach($collection as $c) show_collection($c); } function show_subcat($val) { ?> <div class="sub_node" style="display:none"> <img src="..http://img.dovov.comdtree/join.gif" align="absmiddle" style="padding-left:2px;" /> <a id="'.$val['xsubcatid'].'" href="javascript:void(0)" onclick="getProduct(this , event)" class="sub_node_links" > <?php echo $val['xsubcatname']; ?> </a> </div> <?php } function show_cat($item) { ?> <div class="node" > <img src="..http://img.dovov.comdtree/plus.gif" align="absmiddle" class="node_item" id="plus" /> <img src="..http://img.dovov.comdtree/folder.gif" align="absmiddle" id="folder"> <?php echo $item['xcatname']; ?> <?php $subcat = get_where('xxsubcategory' , array('xcatid'=>$item['xcatid'])) ; foreach($subcat as $val) show_subcat($val); ?> </div> <?php } function show_collection($c) { ?> <div class="parent" style="direction:rtl"> <img src="..http://img.dovov.comdtree/minus.gif" align="absmiddle" class="parent_item" id="minus" /> <img src="..http://img.dovov.comdtree/base.gif" align="absmiddle" id="base"> <?php echo $c['xcollectionname']; ?> <?php //get categories $cat = get_where('xxcategory' , array('xcollectionid'=>$c['xcollectionid'])); foreach($cat as $item) show_cat($item); ?> </div> <?php } ?> 
试图find第一个将是:
 $first = true; foreach ( $obj as $value ) { if ( $first ) { // do something $first = false; //in order not to get into the if statement for the next loops } else { // do something else for all loops except the first } } 
只要这个工程!
 //Store the last key $lastkey = key(end($array)); foreach($array as $key => $element) { ....do array stuff if ($lastkey === key($array)) echo 'LAST ELEMENT!'; } 
  1:为什么不使用简单for陈述? 假设你正在使用一个真正的数组,而不是一个Iterator你可以很容易地检查计数器variables是0还是小于整数个元素。 在我看来,这是最干净和可以理解的解决scheme。 
 $array = array( ... ); $count = count( $array ); for ( $i = 0; $i < $count; $i++ ) { $current = $array[ $i ]; if ( $i == 0 ) { // process first element } if ( $i == $count - 1 ) { // process last element } } 
2:你应该考虑使用嵌套集来存储你的树结构。 另外,你可以通过使用recursion函数来改善整个事情。
最佳答案:
 $arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); foreach ($arr as $a) { // This is the line that does the checking if (!each($arr)) echo "End!\n"; echo $a."\n"; } 
对于SQL查询生成脚本,或者对第一个或最后一个元素执行不同操作的任何操作,要避免使用不必要的variables检查,速度要快得多(快近两倍)。
目前接受的解决scheme在循环中使用循环和检查,将进行every_single_iteration,正确(快速)的方法是这样的:
 $numItems = count($arr); $i=0; $firstitem=$arr[0]; $i++; while($i<$numItems-1){ $some_item=$arr[$i]; $i++; } $last_item=$arr[$i]; $i++; 
一个自制的基准testing显示如下:
test1:模型morg的100000次运行
时间:1869.3430423737毫秒
test2:如果最后一次运行100000次模型
时间:3235.6359958649毫秒
而且很明显,这个支票花了很多钱,当然,你添加的可变支票越多,情况越糟糕;)
 使用一个布尔variables仍然是最可靠的,即使你想检查一个$value的第一个外观(我发现它在我的情况和在许多情况下更有用) ,如下所示: 
 $is_first = true; foreach( $array as $value ) { switch ( $value ) { case 'match': echo 'appeared'; if ( $is_first ) { echo 'first appearance'; $is_first = false; } break; } } if( !next( $array ) ) { echo 'last value'; } } 
 那么怎么样!next( $array )find最后一个$value ,如果没有next()值要迭代,它将返回true 。 
 而我更喜欢使用for循环而不是foreach如果我要使用一个计数器,就像这样: 
 $len = count( $array ); for ( $i = 0; $i < $len; $i++ ) { $value = $array[$i]; if ($i === 0) { // first } elseif ( $i === $len - 1 ) { // last } // … $i++; } 
使用键和值也可以工作:
 foreach ($array as $key => $value) { if ($value === end($array)) { echo "LAST ELEMENT!"; } } 
 与foreach不同,@morg最有效的答案只适用于正确的数组,而不是哈希映射对象。 这个回答避免了循环的每一次迭代的条件语句的开销,就像在大多数这些答案(包括接受的答案)中一样,通过专门处理第一个和最后一个元素,以及在中间元素上循环。 
  array_keys函数可以用来使有效的答案像foreach一样工作: 
 $keys = array_keys($arr); $numItems = count($keys); $i=0; $firstItem=$arr[$keys[0]]; # Special handling of the first item goes here $i++; while($i<$numItems-1){ $item=$arr[$keys[$i]]; # Handling of regular items $i++; } $lastItem=$arr[$keys[$i]]; # Special handling of the last item goes here $i++; 
我没有在这方面做过基准testing,但没有添加任何逻辑,这是对性能的最大打击,所以我怀疑提供有效答案的基准是非常接近的。
如果你想这样的function ,我已经在这里iterateList函数摆动。 尽pipe如此,如果您非常关心效率,您可能需要对基本代码进行基准testing。 我不确定函数调用引入了多less开销。
当我遇到同样的问题时,我遇到了这个线程。 我只需要得到第一个元素,然后重新分析我的代码,直到出现在我的脑海里。
 $firstElement = true; foreach ($reportData->result() as $row) { if($firstElement) { echo "first element"; $firstElement=false; } // Other lines of codes here } 
上面的代码是伟大而完整的,但如果你只需要第一个元素,那么你可以试试这个代码。
 不知道是否仍然有必要。 但下面的解决scheme应该与迭代器一起工作,不需要count 。 
 <?php foreach_first_last(array(), function ($key, $value, $step, $first, $last) { echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL; }); foreach_first_last(array('aa'), function ($key, $value, $step, $first, $last) { echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL; }); echo PHP_EOL; foreach_first_last(array('aa', 'bb', 'cc'), function ($key, $value, $step, $first, $last) { echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL; }); echo PHP_EOL; function foreach_first_last($array, $cb) { $next = false; $current = false; reset($array); for ($step = 0; true; ++$step) { $current = $next; $next = each($array); $last = ($next === false || $next === null); if ($step > 0) { $first = $step == 1; list ($key, $value) = $current; if (call_user_func($cb, $key, $value, $step, $first, $last) === false) { break; } } if ($last) { break; } } } 
尝试这个:
 function children( &$parents, $parent, $selected ){ if ($parents[$parent]){ $list = '<ul>'; $counter = count($parents[$parent]); $class = array('first'); foreach ($parents[$parent] as $child){ if ($child['id'] == $selected) $class[] = 'active'; if (!--$counter) $class[] = 'last'; $list .= '<li class="' . implode(' ', $class) . '"><div><a href="]?id=' . $child['id'] . '" alt="' . $child['name'] . '">' . $child['name'] . '</a></div></li>'; $class = array(); $list .= children($parents, $child['id'], $selected); } $list .= '</ul>'; return $list; } } $output .= children( $parents, 0, $p_industry_id);