Найти последний элемент массива при использовании цикла foreach в PHP

Я пишу создателя SQL-запросов, используя некоторые параметры. В Java очень легко обнаружить последний элемент массива из цикла for, просто проверив текущую позицию массива с длиной массива.

for(int i=0; i< arr.length;i++){ boolean isLastElem = i== (arr.length -1) ? true : false; } 

В PHP у них есть нецелые индексы для доступа к массивам. Таким образом, вы должны выполнять итерацию по массиву с использованием цикла foreach. Это становится проблематичным, когда вам нужно принять какое-то решение (в моем случае добавить или / и параметр при построении запроса).

Я уверен, что должен быть какой-то стандартный способ сделать это.

Как вы решаете это на PHP?

Похоже, вы хотите что-то вроде этого:

 $numItems = count($arr); $i = 0; foreach($arr as $key=>$value) { if(++$i === $numItems) { echo "last index!"; } } 

При этом вы не хотите – перебирать «массив», используя foreach в php.

Вы можете получить значение последнего ключа массива с помощью end(array_keys($array)) и сравнить его с текущим ключом:

 $last_key = end(array_keys($array)); foreach ($array as $key => $value) { if ($key == $last_key) { // last element } else { // not last element } } 

почему так сложно?

 foreach($input as $key => $value) { $ret .= "$value"; if (next($input)==true) $ret .= ","; } 

Это добавит за каждым значением, кроме последнего!

Когда toEnd достигает 0, это означает, что он находится на последней итерации цикла.

 $toEnd = count($arr); foreach($arr as $key=>$value) { if (0 === --$toEnd) { echo "last index! $value"; } } 

Последнее значение по-прежнему доступно после цикла, поэтому, если вы просто хотите использовать его для большего количества материалов после цикла, это лучше:

 foreach($arr as $key=>$value) { //something } echo "last index! $key => $value"; 

Если вы не хотите рассматривать последнее значение как специальные внутренние циклы. Это должно быть быстрее, если у вас большие массивы. (Если вы повторно используете массив после цикла внутри той же области действия, вам нужно сначала «скопировать» массив).

 //If you use this in a large global code without namespaces or functions then you can copy the array like this: //$array = $originalArrayName; //uncomment to copy an array you may use after this loop //end($array); $lastKey = key($array); //uncomment if you use the keys $lastValue = array_pop($array); //do something special with the last value here before you process all the others? echo "Last is $lastValue", "\n"; foreach ($array as $key => $value) { //do something with all values before the last value echo "All except last value: $value", "\n"; } //do something special with the last value here after you process all the others? echo "Last is $lastValue", "\n"; 

И ответить на ваш оригинальный вопрос «в моем случае добавить или / и параметр при построении запроса»; это будет охватывать все значения, а затем объединить их в строку с «и» между ними, но не до первого значения или после последнего значения:

 $params = []; foreach ($array as $value) { $params[] = doSomething($value); } $parameters = implode(" and ", $params); 

Есть уже много ответов, но стоит также заглянуть в итераторы, тем более, что его попросили стандартный способ:

 $arr = range(1, 3); $it = new CachingIterator(new ArrayIterator($arr)); foreach($it as $key => $value) { if (!$it->hasNext()) echo 'Last:'; echo $value, "\n"; } 

Вы можете найти что-то, что делает более гибким и для других случаев.

Итак, если ваш массив имеет уникальные значения массива, то определение последней итерации тривиально:

 foreach($array as $element) { if ($element === end($array)) echo 'LAST ELEMENT!'; } 

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

 foreach($array as $key => $element) { end($array); if ($key === key($array)) echo 'LAST ELEMENT!'; } 

Также обратите внимание на строгий оператор соприкосновения, что в этом случае весьма важно.

Предполагая, что у вас есть массив, хранящийся в переменной …

 foreach($array as $key=>$value) { echo $value; if($key != count($array)-1) { echo ", "; } } 

Если вам нужно что-то сделать для каждого элемента, кроме первого или последнего, и только если в массиве имеется более одного элемента, я предпочитаю следующее решение.

Я знаю, что существует много решений выше и размещено месяцев / за год до моего, но это то, что я чувствую, довольно элегантно. Проверка каждого цикла также является логической проверкой, в отличие от числовой проверки «i = (счет-1)», что может позволить уменьшить накладные расходы.

Структура цикла может показаться неудобной, но вы можете сравнить ее с упорядочением тегов (начало), tfoot (end), tbody (current) в тегах HTML-таблицы.

 $first = true; foreach($array as $key => $value) { if ($first) { $first = false; // Do what you want to do before the first element echo "List of key, value pairs:\n"; } else { // Do what you want to do at the end of every element // except the last, assuming the list has more than one element echo "\n"; } // Do what you want to do for the current element echo $key . ' => ' . $value; } 

Например, в терминах веб-разработки, если вы хотите добавить border-bottom для каждого элемента, кроме последнего в неупорядоченном списке (ul), тогда вы можете вместо этого добавить границу-верхнюю часть для каждого элемента, кроме первого (CSS: first-child, поддерживаемый IE7 + и Firefox / Webkit, поддерживает эту логику, тогда как: последний-ребенок не поддерживается IE7).

Вы можете свободно повторно использовать переменную $ first для каждого вложенного цикла, и все будет работать нормально, поскольку каждый цикл делает $ first false во время первого процесса первой итерации (так что breaks / exceptions не вызовут проблем) ,

 $first = true; foreach($array as $key => $subArray) { if ($first) { $string = "List of key => value array pairs:\n"; $first = false; } else { echo "\n"; } $string .= $key . '=>('; $first = true; foreach($subArray as $key => $value) { if ($first) { $first = false; } else { $string .= ', '; } $string .= $key . '=>' . $value; } $string .= ')'; } echo $string; 

Пример вывода:

 List of key => value array pairs: key1=>(v1_key1=>v1_val1, v1_key2=>v1_val2) key2=>(v2_key1=>v2_val1, v2_key2=>v2_val2, v2_key3=>v2_val3) key3=>(v3_key1=>v3_val1) 

Это должен быть простой способ найти последний элемент:

 foreach ( $array as $key => $a ) { if ( end( array_keys( $array ) ) == $key ) { echo "Last element"; } else { echo "Just another element"; } } 

Ссылка: Ссылка

Вы все равно можете использовать этот метод с ассоциативными массивами:

 $keys = array_keys($array); for ($i = 0, $l = count($array); $i < $l; ++$i) { $key = $array[$i]; $value = $array[$key]; $isLastItem = ($i == ($l - 1)); // do stuff } // or this way... $i = 0; $l = count($array); foreach ($array as $key => $value) { $isLastItem = ($i == ($l - 1)); // do stuff ++$i; } 

У меня сильное чувство, что в корне этой «проблемы XY» OP хотел просто функцию implode() .

Похоже, вы хотите что-то вроде этого:

 $array = array( 'First', 'Second', 'Third', 'Last' ); foreach($array as $key => $value) { if(end($array) === $value) { echo "last index!" . $value; } } 

Поскольку ваше намерение найти массив EOF – это просто клей. Познакомиться с нижеприведенной тактикой. Вам не требуется EOF:

 $given_array = array('column1'=>'value1', 'column2'=>'value2', 'column3'=>'value3'); $glue = ''; foreach($given_array as $column_name=>$value){ $where .= " $glue $column_name = $value"; //appending the glue $glue = 'AND'; } echo $where; 

о / р:

 column1 = value1 AND column2 = value2 AND column3 = value3 

вы можете сделать count ().

 for ($i=0;$i<count(arr);$i++){ $i == count(arr)-1 ? true : false; } 

или если вы ищете ТОЛЬКО последний элемент, вы можете использовать end ().

 end(arr); 

возвращает только последний элемент.

и, как оказалось, вы МОЖЕТЕ индексировать массивы php целыми числами. Это прекрасно

 arr[1]; 

Как насчет использования «конца»? http://php.net/manual/en/function.end.php

Вы также можете сделать что-то вроде этого:

 end( $elements ); $endKey = key($elements); foreach ($elements as $key => $value) { if ($key == $endKey) // -- this is the last item { // do something } // more code } 

Мне нравится следующее, поскольку я чувствую, что это довольно аккуратно. Предположим, мы создаем строку с разделителями между всеми элементами: например, a, b, c

 $first = true; foreach ( $items as $item ) { $str = ($first)?$first=false:", ".$item; } 

Одним из способов может быть обнаружение next итератора. Если на итераторе нет следующего, это означает, что вы находитесь в последнем цикле.

 foreach ($some_array as $element) { if(!next($some_array)) { // This is the last $element } } 

Вот еще один способ сделать это:

 $arr = range(1, 10); $end = end($arr); reset($arr); while( list($k, $v) = each($arr) ) { if( $n == $end ) { echo 'last!'; } else { echo sprintf('%s ', $v); } } 

Если я вас понимаю, тогда вам нужно только отменить массив и получить последний элемент с помощью команды pop:

  $rev_array = array_reverse($array); echo array_pop($rev_array); 

Вы также можете попробовать это сделать свой запрос … показанный здесь с помощью INSERT

 <?php $week=array('one'=>'monday','two'=>'tuesday','three'=>'wednesday','four'=>'thursday','five'=>'friday','six'=>'saturday','seven'=>'sunday'); $keys = array_keys($week); $string = "INSERT INTO my_table ('"; $string .= implode("','", $keys); $string .= "') VALUES ('"; $string .= implode("','", $week); $string .= "');"; echo $string; ?> 

Для сценариев генерации 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++; в $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 миллисекунд

Другой способ – запомнить предыдущий результат цикла цикла и использовать его в качестве конечного результата:

  $result = $where = ""; foreach ($conditions as $col => $val) { $result = $where .= $this->getAdapter()->quoteInto($col.' = ?', $val); $where .= " AND "; } return $this->delete($result); 

Я лично использую такую ​​конструкцию, которая позволяет легко использовать элементы html <ul> и <li>: просто измените равенство для другого свойства …

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

 $table = array( 'a' , 'b', 'c'); $it = reset($table); while( $it !== false ) { echo 'all loops';echo $it; $nextIt = next($table); if ($nextIt === false || $nextIt === $it) { echo 'last loop or two identical items'; } $it = $nextIt; } 

Вы можете dirctly получить последний индекс:

$numItems = count($arr);

echo $arr[$numItems-1];

 <?php foreach($have_comments as $key => $page_comment): ?> <?php echo $page_comment;?> <?php if($key+1<count($have_comments)): ?> <?php echo ', '; ?> <?php endif;?> <?php endforeach;?> 

Вот мое решение: просто получите счетчик вашего массива, минус 1 (начиная с 0).

 $lastkey = count($array) - 1; foreach($array as $k=>$a){ if($k==$lastkey){ /*do something*/ } } 

У меня есть обобщенное решение, которое я использую для общей цели компиляции строки из массива строковых значений. Все, что я делаю, это добавить необычную строку в конец, а затем заменить ее.

Функция для возврата строки из массива, разделенная, без разделителя трейлинга:

 function returnArraySeparated($aArr, $sSep, $sAdd = "@X@") { $strReturn = (string) ""; # Compile the set: foreach ($aArr as $sItem) { $strReturn .= $sItem . $sSep; } # Easy strip the end: $strReturn = str_replace($sSep . $sAdd, "", $strReturn . $sAdd); return $strReturn; } 

Ничего особенного, но это работает 🙂