Вопрос прост. У меня в коде есть цикл foreach
:
foreach($array as $element) {
//code
}
В этом цикле я хочу реагировать по-разному, когда мы находимся на первой или последней итерации.
Как это сделать?
Если вы предпочитаете решение, которое не требует инициализации счетчика вне цикла, я предлагаю сравнение текущей итерации ключ от функции, которая говорит вам последний / первый ключ массива.
Это становится немного более эффективным (и более читаемым) с наступающим РНР 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!';
}
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++;
}
Более упрощенная версия выше и предполагая, что вы'повторно не используя пользовательские индексы...
$len = count($array);
foreach ($array as $index => $item) {
if ($index == 0) {
// first
} else if ($index == $len - 1) {
// last
}
}
Версия 2 - потому что я пришел, чтобы ненавидеть помощью еще, если надо.
$len = count($array);
foreach ($array as $index => $item) {
if ($index == 0) {
// first
// do something
continue;
}
if ($index == $len - 1) {
// last
// do something
continue;
}
}
Вы можете удалить первый и последний элементы из массива и обрабатывать их отдельно.
Например:
<?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) {
//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="../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
}
?>
Просто это работает!
// 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 для рассортировки конец вопрос.
Попытка найти первый будет:
$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
}
}
1: Почему бы не использовать простой оператор for
? Предполагая, что вы используете реальный массив, а не итератор
, вы могли бы легко проверить, равна ли переменная счетчика 0 или на единицу меньше целого числа элементов. На мой взгляд, это наиболее чистое и понятное решение...
$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 для хранения структуры дерева. Кроме того, вы можете улучшить все это дело, используя рекурсивные функции.
Наиболее эффективного ответа](https://stackoverflow.com/q/6996964) от @морг, в отличие от объекту
, работает только для правильного массивы, а не объекты хэш-карте. Этот ответ позволяет избежать накладных расходов на условный оператор для каждой итерации цикла, как и в большинстве подобных ответов (в том числе принято отвечать) по конкретно обработка первого и последнего элемента, и зацикливание на Ближнем элементов.
В [array_keys
] функция(http://php.net/manual/en/function.array-keys.php) может быть использован для эффективного ответа работы, как объекту
:
$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++;
Я не'т сделать бенчмаркинга на этом, но никакой логики была добавлена в петлю, которая была самой большой удар по производительности не происходит, поэтому я'd и подозреваю, что критерии, предлагаемые с эффективным ответом довольно близки.
Если вы хотели functionalize такого рода вещи, я'вэ наезжал на такой функция iterateList здесь. Хотя, вы, возможно, захотите, чтобы тест код, суть если вы'вновь переживать об эффективности. Я'м не знаете, какую нагрузку все функции вызова, вводится.
Для генерации 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++;
Небольшой домашний тест показал следующее:
тест1: 100000 прогонов модели морг
время: 1869.3430423737 миллисекунд
условие_2: 100000 прогонов модели, если последний
время: 3235.6359958649 миллисекунд
И это's, таким образом, совершенно ясно, что проверка стоит дорого, и конечно, это становится еще хуже, чем больше переменных проверяет тебя добавить ;)
Используя логическую переменную по-прежнему самый надежный, даже если вы хотите проверить первое появление стоимостью $
(я нашел его более полезным в моей ситуации и во многих ситуациях), таких, как этот:
$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';
}
}
Тогда как насчет !следующий( $массив ), чтобы найти значение$последние `` который возвращает
true, если там's нет
значение следующий()` для перебора.
И я предпочитаю использовать для
петли вместо 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
}
Приведенные выше коды являются прекрасной и полной, но если вам нужен только первый элемент, то вы можете попробовать этот код.
Не уверен, если это еще необходимо. Но следующее решение должно работать с итераторами и не требует граф
.
<?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
}
});
Еще три вещи должны быть упомянуты:
вы должны пройти по ссылке (
&$элемент`).внутри
использовать` построить снова, ссылка, Если это необходимо.Вы можете использовать счетчик и длина массива.
в <предварительно> $массив = массив(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();
}
}
Попробуйте это:
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);