如果您更喜欢不需要在循环外初始化计数器的解决方案,那么您可以将当前迭代键与告诉您数组的最后一个/第一个键的函数进行比较。
PHP 7.3 及更新版本:
foreach ($array as $key => $element) {
if ($key === array_key_first($array)) {
echo 'FIRST ELEMENT!';
}
if ($key === array_key_last($array)) {
echo 'LAST ELEMENT!';
}
}
PHP 7.2 及更早版本:
PHP 7.2 已经 EOL(生命终结),所以这里只是作为历史参考。避免使用。
foreach ($array as $key => $element) {
reset($array);
if ($key === key($array)) {
echo 'FIRST ELEMENT!';
}
end($array);
if ($key === key($array)) {
echo 'LAST ELEMENT!';
}
}
您可以使用计数器:
$i = 0;
$len = count($array);
foreach ($array as $item) {
if ($i == 0) {
// first
} else if ($i == $len - 1) {
// last
}
// …
$i++;
}
array_shift
和 array_pop
那样垃圾。虽然如果我必须实施这样的事情,这是我想出的解决方案,但我现在会坚持 Rok Kralj's 的答案。
$i = 1
,则不必担心 $len - 1
,只需使用 $len
。
为了找到最后一项,我发现这段代码每次都有效:
foreach( $items as $item ) {
if( !next( $items ) ) {
echo 'Last Item';
}
}
[true,true,false,true]
这样的数组而失败。但就我个人而言,每当我处理一个不包含布尔 false
的数组时,我都会使用它。
next()
应该绝不在 foreach 循环中使用。它弄乱了内部数组指针。查看文档以获取更多信息。
上面的更简化版本并假设您没有使用自定义索引...
$len = count($array);
foreach ($array as $index => $item) {
if ($index == 0) {
// first
} else if ($index == $len - 1) {
// last
}
}
版本 2 - 因为除非必要,否则我开始讨厌使用 else。
$len = count($array);
foreach ($array as $index => $item) {
if ($index == 0) {
// first
// do something
continue;
}
if ($index == $len - 1) {
// last
// do something
continue;
}
}
if ($index == count($array) - 1)
不会对性能造成任何影响。请参阅here。
您可以从数组中删除第一个和最后一个元素并分别处理它们。
像这样:
<?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
?>
将所有格式删除为 CSS 而不是内联标签将改善您的代码并加快加载时间。
您还可以尽可能避免将 HTML 与 php 逻辑混合。
通过分离如下内容可以使您的页面更具可读性和可维护性:
<?php
function create_menu($params) {
//retrieve 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="../images/dtree/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="../images/dtree/plus.gif" align="absmiddle" class="node_item" id="plus" />
<img src="../images/dtree/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="../images/dtree/minus.gif" align="absmiddle" class="parent_item" id="minus" />
<img src="../images/dtree/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
}
?>
尝试找到第一个将是:
$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
}
}
这很有效!
// Set the array pointer to the last key
end($array);
// Store the last key
$lastkey = key($array);
foreach($array as $key => $element) {
....do array stuff
if ($lastkey === key($array))
echo 'THE LAST ELEMENT! '.$array[$lastkey];
}
感谢@billynoah 整理出最终问题。
if ($key === $lastkey)
。
if ($lastkey === $key)
吗?
PHP Warning: key() expects parameter 1 to be array, integer given in php shell code on line 1
key()
得到一个整数,而不是 end()
。 end()
“返回最后一个元素的值”,并且 key()
需要一个数组作为输入。
1:为什么不使用简单的 for
语句?假设您使用的是真实数组而不是 Iterator
,您可以轻松检查计数器变量是 0 还是比元素的总数少 1。在我看来,这是最干净、最容易理解的解决方案......
$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:您应该考虑使用 Nested Sets 来存储您的树结构。此外,您可以通过使用递归函数来改进整个事情。
for
,您可以从 1
循环到 n-1
,然后将 if
从正文中取出。没有必要反复检查它们。
最佳答案:
$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";
}
@morg 中的大多数 efficient answer 与 foreach
不同,仅适用于正确的数组,而不适用于哈希映射对象。这个答案避免了循环的每次迭代的条件语句的开销,就像在大多数这些答案(包括接受的答案)中,专门处理第一个和最后一个元素,并在中间元素上循环.
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++;
我还没有对此进行基准测试,但是没有在循环中添加任何逻辑,这是对性能的最大打击,所以我怀疑提供有效答案的基准非常接近。
如果您想功能化这种东西,我已经尝试过这样的 iterateList function here。不过,如果您非常关心效率,您可能希望对 gist 代码进行基准测试。我不确定所有函数调用引入了多少开销。
对于 SQL 查询生成脚本,或对第一个或最后一个元素执行不同操作的任何脚本,避免使用不必要的变量检查要快得多(几乎快两倍)。
当前接受的解决方案使用循环和循环内的检查,将进行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++;
一个自制的小基准测试显示以下内容:
test1:100000 次运行模型 morg
时间:1869.3430423737 毫秒
test2:100000 次运行模型(如果最后)
时间:3235.6359958649 毫秒
因此很明显,检查成本很高,当然,您添加的可变检查越多,情况就会变得更糟;)
$arr = array('one' => "1 1 1", 4 => 'Four', 1 => 'One'); $numItems = count($arr); $i=0; $firstitem=$arr[0]; echo $i . ': ' . $firstitem . ", "; $i++; while($i<$numItems-1){ $some_item=$arr[$i]; echo $i . ': ' . $some_item . ", "; $i++; } $last_item=$arr[$i]; echo $i . ': ' . $last_item . ", "; $i++;
将输出:0: , 1: One, 2: ,
array()
是 {'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"}
,但空元素会被计数忽略,您正在计算已定义“事物”的数量!赏金牺牲来了!这个答案值得赏金,但如果@Morg.走了,没意义。我会给一个可能不会再使用 SO 的人赏金!如果他回来并改进他的答案,他应该得到赏金!
array_keys
函数获取散列的属性,您可以将其视为数组。请参阅my "improved" answer。
$querySet = ""; foreach ($fieldSet as $key=>$value) { $value = $db->dbLink->quote($value); $querySet .= "$key = $value, "; } $querySet = substr_replace($querySet, "", -2); $queryString = "UPDATE users SET $querySet WHERE user_ID = '$user_ID'";
使用键和值也可以:
foreach ($array as $key => $value) {
if ($value === end($array)) {
echo "LAST ELEMENT!";
}
}
使用布尔变量仍然是最可靠的,即使您想检查 $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()
值,那么 !next( $array )
如何找到最后一个返回 true
的 $value
。
如果要使用计数器,我更喜欢使用 for
循环而不是 foreach
,如下所示:
$len = count( $array );
for ( $i = 0; $i < $len; $i++ ) {
$value = $array[$i];
if ($i === 0) {
// first
} elseif ( $i === $len - 1 ) {
// last
}
// …
$i++;
}
当我遇到同样的问题时,我遇到了这个线程。我只需要获取第一个元素,然后重新分析我的代码,直到我想到这一点。
$firstElement = true;
foreach ($reportData->result() as $row)
{
if($firstElement) { echo "first element"; $firstElement=false; }
// Other lines of codes here
}
上面的代码很棒而且很完整,但是如果你只需要第一个元素,那么你可以试试这个代码。
使用 reset($array) 和 end($array)
<?php
$arrays = [1,2,3,4,5];
$first = reset($arrays);
$last = end($arrays);
foreach( $arrays as $array )
{
if ( $first == $array )
{
echo "<li>{$array} first</li>";
}
else if ( $last == $array )
{
echo "<li>{$array} last</li>";
}
else
{
echo "<li>{$array}</li>";
}
}
不确定是否还有必要。但以下解决方案应该适用于迭代器,并且不需要 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;
}
}
}
您也可以使用匿名函数:
$indexOfLastElement = count($array) - 1;
array_walk($array, function($element, $index) use ($indexOfLastElement) {
// do something
if (0 === $index) {
// first element‘s treatment
}
if ($indexOfLastElement === $index) {
// last not least
}
});
还应该提到三件事:
如果您的数组没有严格(数字)索引,您必须首先通过 array_values 管道您的数组。
如果您需要修改 $element,您必须通过引用 (&$element) 传递它。
您需要在匿名函数之外的任何变量,您必须将它们列在 use 构造内的 $indexOfLastElement 旁边,如果需要,再次引用。
您可以使用计数器和数组长度。
$array = array(1,2,3,4); $i = 0; $len = count($array); foreach ($array as $item) { if ($i === 0) { // first } else if ($i === $len - 1) { // last } // … $i++; }
foreach ($arquivos as $key => $item) {
reset($arquivos);
// FIRST AHEAD
if ($key === key($arquivos) || $key !== end(array_keys($arquivos)))
$pdf->cat(null, null, $key);
// LAST
if ($key === end(array_keys($arquivos))) {
$pdf->cat(null, null, $key)
->execute();
}
}
最简单的方法是
$array = [9,5,6,4,7,8];
$current_iteration = 0;
foreach($array as $item){
if( 0 === $current_iteration ){
echo 'this is the first item: ' . $item;
}
if( (count($array) - 1) === $current_iteration){
echo 'this is the last item: ' . $item;
}
$current_iteration++;
}
尝试这个:
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);
end()
+key()
- 如果两者都是,那么每次都会调用 4 个方法。当然,这些将是非常轻量级的操作,可能只是指针查找,但随后文档确实继续指定reset()
和end()
modify 数组的内部指针 - 所以它比柜台?可能不是。reset()
调用移到 foreach 之前,并将结果缓存在$first
中。