Как узнать последний цикл php

Как узнать последний цикл php thumbnail

Часто бывает нужно определить последнюю итерацию цикла. Как это лучше сделать?

Kromster

12k1212 золотых знаков3737 серебряных знаков6666 бронзовых знаков

задан 12 сен ’12 в 15:36

helegheleg

40888 серебряных знаков2121 бронзовый знак

7

Вычисление каждый раз

for (i = 0; i < m_i; last = ((++i + 1) === m_i)) { abc(); if (last) efg(); xyz(); }

Вычисление один раз

last = false; for (i = 0; (i < m_i – 1) || (last = !last); i++) { abc(); if (last) efg(); xyz(); }

Разнесённая обработка

for (i = 0; i < m_i – 1; i++) { abc(); xyz(); } if (i < m_i) { abc(); efg(); xyz(); }

Редкий, но идеальный случай:

for (i = m_i – 1; i >= 0; –i) { abc(); if (!i) efg(); xyz(); }

ответ дан 12 сен ’12 в 16:38

timka_stimka_s

6,5491010 серебряных знаков2020 бронзовых знаков

В общем случае – никак. Цикл for управляется предикатом, который теоретически может иметь любую внутреннюю логику. Однако если для переменной цикла возможно объявить функцию next(), которая будет возвращать следующее значение, то возможно сделать такой трюк (C++):

#include <string> #include <iostream> using namespace std; string::iterator next(string::iterator i) { return ++i; } main() { string nums = “12345”; for (string::iterator i = nums.begin(); i != nums.end(); ++i) { if (next(i) != nums.end()) cout << *i << endl; else cout << *i << ” (это последняя)” << endl; } }

ответ дан 12 сен ’12 в 16:38

ShamovShamov

2,88911 золотой знак99 серебряных знаков2323 бронзовых знака

Вычислить условие в самом теле.

for(инициализация; условие; инкремент) { if (!условие) (выйти из цикла) }

А еще можно сделать цикл бесконечным и выходить из него через if

#define ever ;; for(ever) { if (условие выхода) (выйти из цикла) }

ответ дан 12 сен ’12 в 15:47

igumnovigumnov

7,5082424 серебряных знака4848 бронзовых знаков

А если не пытаться определять последнюю итерацию цикла, а сознательно “прыгнуть” в нее?

int i; for(i=0; i < n; i++) { System.out.ln(“For cycle iteration=”+i); } //сознательно прыгаем в последнюю итерацию цикла i–; //после завершения цикла i=n System.out.ln(“Last iteration again”+i);

ответ дан 14 сен ’12 в 4:56

Barmaley♦Barmaley

79.7k66 золотых знаков6666 серебряных знаков145145 бронзовых знаков

Во многих языках принцип одинаков: for() содержит три выражения, первое из которых выполняется в начале, второе выполняется перед итерацией, если возвращает TRUE, третье – после итерации. Можно прямо в этих выражениях узнавать, последняя ли итерация грядёт. Напр. на PHP:

for( $i=0; $i<=10; $last = $i++ == 10) { if( $last) { // последний раунд } // обычные действия }

tutankhamun

11.2k55 золотых знаков2323 серебряных знака3838 бронзовых знаков

ответ дан 12 сен ’12 в 16:15

SergiksSergiks

30.3k33 золотых знака4444 серебряных знака8181 бронзовый знак

Всё ещё ищете ответ? Посмотрите другие вопросы с метками циклы или задайте свой вопрос.

Источник

  • #1

Определить последнюю итерацию

Какой правильный способ определить, является ли данная итерация цикла последней?

Обычно пользовался смарти, где подобного вопроса не возникало, а в php-шаблонах только всякие костыли приходят в голову чтобы это реализовать.

Просмотрел spl’ные итераторы, там вроде тоже такого нет.

  • #2

Наверное, нет. Лучше просто передать в шаблон переменную, содержащую последний ключ. Через end и key.

  • #3

а зачем определять последнюю?

  • #4

zerkms

Ну скажем crumbs или хлебные крошки сделать, при этом вывести последний тайтл раздела в теге <h1>

  • #6

или чтобы вывести список значений через запятую

  • #7

Эм, для списка значений есть join(‘,’, $array), не?

  • #8

а если каждое значение надо сделать ссылкой, не?)

  • #9

Эм, просто я вообще не понял каким боком к “последней итерации” было это:

или чтобы вывести список значений через запятую

Потому и написал про джоин. А так вообще цикл по массиву.

  • #10

Автор оригинала: c0dex

Эм, просто я вообще не понял каким боком к “последней итерации” было это:

а как сделаешь чтобы после последнего элемента не выводилась запятая?

-~{}~ 31.08.10 16:54:

например надо вывести список тегов к новости, каждый тег ссылка, разделены запятыми

  • #11

а как сделаешь чтобы после последнего элемента не выводилась запятая?

я в таких случаях добавляю запятую перед всеми, кроме первого

Читайте также:  Клеточного цикла соматической клетки

foreach ($ as $i => $val)

{

if ($i != 0) { $result .= ‘, ‘; }

$result .= ‘<a href…’;

}

альтернативный вариант – добавлять всегда, а потом substr’ом выпилить два знака (запятая + пробел)

ну как-то так

  • #12

если ключи идут по порядку, то можно легко выводить и после

if ($i < count($)-1) …

альтернативный вариант – добавлять всегда, а потом substr’ом выпилить два знака (запятая + пробел)

это вообще не вариант для случая, когда шаблон не собирается сначала в строку

я вообще надеялся что можно сделать как нибудь так

PHP:

$iterator = new ArrayIterator($); foreach ($iterator as $tag) { if (!$iterator->isLast()) … }

ну раз так нельзя, способ сделать менее красиво я сам выберу)

всем спасибо

  • #14

он и на последней итерации будет valid()

-~{}~ 31.08.10 17:25:

я вот такой код придумал) хотя немного страшно выглядит)

PHP:

$ = array(“1”, “2”, “3”, “4”); $iterator = new ArrayIterator($); while ($iterator->valid()) { echo $iterator->current(); $iterator->next(); if ($iterator->valid()) { echo “, “; } }

  • #16

Я бы сделал цикл по всем тэгам, сделал их ссылками, а потом соединил через join()

  • #17

c0dex

если делать это в контролерре – там появится HTML

если в представлении, то слишком много логики для него

  • #18

Beavis

это лично дело каждого как делать, я делаю в представлении, так как это к нему относится формировать списки и работать с такими вещами в цикле, плюс оформление 100% должно быть в шаблоне, а не в контроллере.

  • #19

Обычно пользовался смарти, где подобного вопроса не возникало, а в php-шаблонах только всякие костыли приходят в голову чтобы это реализовать.

А посмотри, какой код генерирует Smarty… Не лучше, чем в “PHP”. По сути, Smarty – обертка над PHP с добавлением некоторого функционала. Но это не значит, что в PHP по-умолчанию он должен присутствовать. Нужен, а нету – значит надо написать.

Если бы уж красивость была так критична, то смотрел бы в сторону этого варианта:

Код:

class ArrayIteratorExtended extends ArrayIterator { private $_last_index; public __construct(array $array) { parent::__construct($array); $keys = array_keys($array); $this->_last_index = end($keys); } public isLast() { return $this->_last_index==$this->key(); } } $ = array(“1”, “2”, “3”, “4”); $iterator = new ArrayIteratorExtended($); foreach ($iterator as $tag) { echo $tag; if (!$iterator->isLast()) { echo ‘, ‘; } }

  • #20

да это всё понятно, спасибо, просто перед тем как делать велосипед, надо было убедиться что php таких возможностей не предоставляет.

Источник

В этом цикле я хочу реагировать по-разному, когда мы находимся на первой или последней итерации.

Вы можете использовать счетчик:

$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. Для них вы можете кэшировать значение ключа перед циклом.

reset($array); $first = key($array); foreach($array as $key => $element) { if ($key === $first) echo ‘FIRST ELEMENT!’; }

Чтобы найти последний элемент, я считаю, что этот кусок кода работает каждый раз:

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 } }

Версия 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 create_($params) { //retirive items //get collection $collection = get(‘xxcollection’) ; foreach($collection as $c) show_collection($c); } show_subcat($val) { ?> <div class=”sub_node” style=””> <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_s” > <?php echo $val[‘xsubcatname’]; ?> </a> </div> <?php } 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(‘xxsub’ , array(‘xcatid’=>$item[‘xcatid’])) ; foreach($subcat as $val) show_subcat($val); ?> </div> <?php } 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(‘xx’ , 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 ement 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 вы можете легко проверить, равна ли переменная счетчика 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 для хранения вашей древовидной структуры. Кроме того, вы можете улучшить все это, используя рекурсивные функции.

Лучший ответ:

$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-запросов или всего, что делает другое действие для первого или последнего элемента, оно намного быстрее (почти в два раза быстрее), чтобы избежать использования проверок ненужных переменных.

Текущее принятое решение использует цикл и проверку внутри цикла, которые будут сделаны every__iteration, правильный (быстрый) способ сделать это следующий:

$numItems = count($arr); $i=0; $firstitem=$arr[0]; $i++; while($i<$numItems-1){ $some_item=$arr[$i]; $i++; } $last_item=$arr[$i]; $i++; в $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 прогонов модели морга

время: 1869.3430423737 миллисекунды

test2: 100000 пробегов модели, если последняя

время: 3235.6359958649 миллисекунд

И вполне понятно, что проверка стоит много, и, конечно же, становится еще хуже, чем больше проверяет переменные;)

Использование логической переменной по-прежнему является самым надежным, даже если вы хотите проверить первое появление значения $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 ) чтобы найти последнее $value которое вернет true если нет next() значения для итерации.

И я предпочитаю использовать цикл for вместо foreach если я собираюсь использовать счетчик, например:

Читайте также:  Структура и использование цикла while

$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!”; } }

Самый эффективный ответ от @morg, в отличие от 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++; в $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 . Хотя, возможно, вы захотите провести сравнение кода gist, если вы серьезно обеспокоены эффективностью. Я не уверен, сколько накладных расходов вызывает все функции invocation.

Я столкнулся с этим вопросом, когда у меня такая же проблема. Мне нужно только получить первый элемент, тогда я переанализирую свой код, пока это не придет мне в голову.

$firstElement = true; foreach ($reportData->result() as $row) { if($firstElement) { echo “first element”; $firstElement=false; } // Other lines of codes here }

Вышеприведенные коды являются большими и полными, но если вам нужен только первый элемент, вы можете попробовать этот код.

Не уверен, что это все еще необходимо. Но следующее решение должно работать с итераторами и не требует count .

<?php foreach_first_last(array(), ($key, $value, $step, $first, $last) { echo intval($first), ‘ ‘, intval($last), ‘ ‘, $step, ‘ ‘, $value, PHP_EOL; }); foreach_first_last(array(‘aa’), ($key, $value, $step, $first, $last) { echo intval($first), ‘ ‘, intval($last), ‘ ‘, $step, ‘ ‘, $value, PHP_EOL; }); echo PHP_EOL; foreach_first_last(array(‘aa’, ‘bb’, ‘cc’), ($key, $value, $step, $first, $last) { echo intval($first), ‘ ‘, intval($last), ‘ ‘, $step, ‘ ‘, $value, PHP_EOL; }); echo PHP_EOL; 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, ($element, $index) use ($indexOfLastElement) { // do something if (0 === $index) { // first element’s treatment } if ($indexOfLastElement === $index) { // last not least } });

Следует упомянуть еще три вещи:

  • Если ваш массив не индексируется строго (численно), вы должны сначала array_values свой массив через array_values .
  • Если вам нужно изменить $element вы должны передать его по ссылке ( &$element ).
  • Любые переменные извне анонимной функции, которые вам нужны внутри, вам нужно будет перечислить их рядом с $indexOfLastElement внутри use конструкции, опять же по ссылке, если необходимо.

Попробуй это:

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);

Источник