Я пишу создателя 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; }
Ничего особенного, но это работает 🙂