Вопрос простой. В моем коде есть цикл foreach
:
foreach($array as $element) {
//code
}
В этом цикле я хочу по-другому реагировать, когда мы находимся на первой или последней итерации.
Как это сделать?
Вопрос простой. В моем коде есть цикл 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++;
}
array_shift
и array_pop
. Хотя это решение, которое я придумал, если бы мне пришлось реализовать такую вещь, я бы сейчас придерживался ответа Рока Краля.
- person shadyyx; 15.05.2013
$i = 1
, вам не нужно беспокоиться о $len - 1
, просто используйте $len
.
- person aksu; 03.04.2015
for
не работает с ассоциативным массивом.
- person billynoah; 28.12.2018
$i
, просто используйте индекс foreach: foreach ($array as $index => $item) {
затем в остальной части кода замените все $i
на $index
.
- person Fellipe Sanches; 04.12.2019
Если вы предпочитаете решение, которое не требует инициализации счетчика вне цикла, я предлагаю сравнить текущий ключ итерации с функцией, которая сообщает вам последний / первый ключ массива.
Это станет несколько более эффективным (и более читаемым) с выходом 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!';
}
foreach($array as $key => $element) {
reset($array);
if ($key === key($array))
echo 'FIRST ELEMENT!';
end($array);
if ($key === key($array))
echo 'LAST ELEMENT!';
}
end()
+ key()
на каждой итерации цикла - если оба, то каждый раз вызывается 4 метода. Конечно, это были бы очень легкие операции и, вероятно, просто поиск указателя, но затем в документации указывается, что reset()
и end()
изменяют внутренний указатель массива - так что это быстрее, чем счетчик? возможно, нет.
- person pospi; 20.06.2012
reset()
перед foreach и кэшировать результат в $first
.
- person Rok Kralj; 17.01.2013
$element
с $array[0]
?
- person Chibueze Opata; 12.03.2013
$array = array('a' => 1, 'b' => 2)
, тогда $array[0]
вернет NULL и выдаст уведомление.
- person Rok Kralj; 12.03.2013
foreach($array as $key=>&$value)
. В этом случае он сбросит счетчик итераций. Использовать стандартный foreach($array as $key=>$value)
- person Mladen Janjetovic; 16.05.2013
last(&$array, $key)
) вы фактически установите указатель исходного массива на последний элемент. Без &
этого не произойдет, потому что это копия исходного массива. Я бы удалил &
. Эта функция потребляет больше памяти, но может предотвратить некоторые неожиданные действия.
- person dbroeks; 07.03.2014
Чтобы найти последний элемент, я считаю, что этот фрагмент кода работает каждый раз:
foreach( $items as $item ) {
if( !next( $items ) ) {
echo 'Last Item';
}
}
[true,true,false,true]
он неизменно терпит неудачу. Но лично я буду использовать это в любое время, когда буду иметь дело с массивом, не содержащим логического false
.
- person billynoah; 10.01.2017
next()
проверкой в цикле foreach, это действительно сложный фрагмент кода. Во-первых, я получаю два уведомления о последнем элементе, а во-вторых, когда next()
вызывается несколько раз (например, в двух разных условиях), происходят чрезвычайно странные вещи. Похоже, что у next()
и foreach()
есть свой собственный указатель на массив. Проверено на PHP 5.5.20.
- person mvds; 16.10.2017
next()
не следует НИКОГДА использовать внутри цикла foreach. Это портит внутренний указатель массива. Ознакомьтесь с документацией для получения дополнительной информации.
- person Drazzah; 17.01.2018
Более упрощенная версия вышеизложенного и предполагающая, что вы не используете пользовательские индексы ...
$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)
не приведет к снижению производительности. См. здесь.
- person Katrina; 26.08.2016
Вы можете удалить первый и последний элементы из массива и обработать их отдельно.
Нравится:
<?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
}
?>
Просто это работает!
// 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)
.
- person Krzysztof Przygoda; 23.12.2015
$lastkey
будет null
, если $array
не ассоциативный массив, таким образом нарушает код
- person Dadan; 07.09.2016
===
, а не ==
?
- person AlexioVay; 29.10.2016
if ($lastkey === $key)
?
- person Kinetic; 13.01.2017
PHP Warning: key() expects parameter 1 to be array, integer given in php shell code on line 1
- person billynoah; 28.12.2018
key()
получает целое число, а не end()
. end()
возвращает значение последнего элемента, а key()
ожидает в качестве входных данных массив.
- person billynoah; 29.12.2018
Попытка найти первый будет:
$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
? Предполагая, что вы используете реальный массив, а не 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. Вам следует рассмотреть возможность использования вложенных наборов для хранения древовидной структуры. Кроме того, вы можете улучшить все это, используя рекурсивные функции.
for
, вы можете сделать цикл от 1
до n-1
и вынуть if
из тела. Нет смысла проверять их повторно.
- person mpen; 28.01.2016
Лучший ответ:
$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, в отличие от 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 здесь. Хотя, возможно, вы захотите протестировать суть кода, если вас очень беспокоит эффективность. Я не уверен, сколько накладных расходов вызывает вызов функций.
Для сценариев генерации 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 прогонов модельного морга
время: 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: ,
- person Seika85; 14.05.2014
array()
сделан {'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"}
, но пустые элементы игнорируются с помощью count, вы подсчитываете количество определенных вещей !! ПРИХОДИТСЯ ЖЕРТВОСТЬ БОНТИ! Этот ответ заслуживает награды, но если @Morg. ушло, это бессмысленно. Я бы наградил человека, который, вероятно, больше не будет использовать ТАК! Если он вернется и улучшит свой ответ, он заслуживает награды!
- person mjz19910; 30.06.2016
array_keys
, которую вы можете рассматривать как массив. См. мой улучшенный ответ.
- person TheMadDeveloper; 02.07.2016
$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'";
- person Rovshan Mamedov; 05.02.2018
С ключами и значениями это тоже работает:
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( $array )
найти последний $value
, который вернет true
, если нет next()
значения для итерации.
И я предпочитаю использовать цикл 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
}
Приведенные выше коды великолепны и полны, но если вам нужен только первый элемент, вы можете попробовать этот код.
Не уверен, что это еще необходимо. Но следующее решение должно работать с итераторами и не требует 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;
}
}
}
Использование 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>";
}
}
Вы также можете использовать анонимную функцию:
$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
).$indexOfLastElement
внутри конструкции use
, при необходимости снова по ссылке.Вы можете использовать счетчик и длину массива.
$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++; }
Попробуй это:
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);