Знайдіть останній елемент масиву, використовуючи цикл foreach у PHP


215

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

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

У PHP вони мають не цілі показники для доступу до масивів. Тому ви повинні повторити масив за допомогою циклу foreach. Це стає проблематичним, коли вам потрібно прийняти якесь рішення (у моєму випадку додати або / і параметр під час створення запиту).

Я впевнений, що для цього повинен бути якийсь стандартний спосіб.

Як ви вирішите це в PHP?


2
Чи намагаєтесь ви визначити, чи слід укладати "І" чи "АБО" між частинами пункту "де"?
Дарріл Хайн

1
просто вказавши, що слід зберігати загальну суму в змінній, а не викликати метод для кожної ітерації. for (int i = 0, int t = arr.length; i <t; i ++).
OIS


Подивіться на це рішення: stackoverflow.com/a/29474468/1478566
vbarbarosh

використовувати end (масив) використовувати
Visakh B Sujathan

Відповіді:


313

Це здається, що ви хочете щось подібне:

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

Як сказано, ви не маєте ітерації через "масив", використовуючи foreachphp.


Я думаю, я піду для цього рішення, оскільки він майже схожий на код, який я розмістив. Навіть відповідь Джеремі добре підходить, але я думаю, що вона мала складний порівняно з цією. Я не проводив жодних тестів, але, мабуть, ця відповідь буде швидшою, оскільки це не витягує масив ключів. Це повинна мати швидкість O (1)
Vaibhav Kamble

18
$numItems = count($arr)трюк не потрібен і зменшує читабельність - у PHP не існує штрафу за продуктивність за доступ до підрахунку ($ arr) кожного разу. Причина полягає в тому, що кількість елементів внутрішньо зберігається як спеціальне поле у ​​заголовку масиву і не обчислюється під час руху. Цей трюк походить з інших мов (C, Java?, ...).
johndodo

7
Це цікаво @johndodo, що не існує штрафу за ефективність кожного разу за доступ до підрахунку ($ arr). Чи є у вас посилання / джерела до того, де саме ця документація оптимізована? Дякую!
zuallauz

2
Дуже сумно, що в PHP найбільш правильне рішення цієї проблеми виглядає досить неелегантно :(
kizzx2

1
@tomsihap $ i потрібно наростити всередині циклу, в тандемі з ітерацією масиву. $ i потрібно представити номер елемента в масиві, щоб з його допомогою можна було визначити, коли досягнуто останній елемент. Без циклу ++ цикл порівнював би лише "0" із загальною кількістю елементів.
Боббі Джек

201

Ви можете отримати значення останнього ключа масиву за допомогою 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
    }
}

2
+1 Я згоден - інші рішення покладаються на масив, що має числові індекси.
Патрік Glandien

19
На мою власну захист моя відповідь не покладається на те, що масив має цифрові клавіші :)
Річард Левассер

2
Порівняння рядків повільніше, ніж цілі числа, і не завжди точне при порівнянні рядків з цілими числами (ви повинні принаймні використовувати ===). Я голосую за це.
OIS

4
це елегантно, але викликає СТРИКТНЕ ВІДПОВІДЬ, оскільки "end" очікує опорного значення :(
Wiliam

10
Виправлення для СТРАХОВОГО ВІДПОВІДЬ:$lastKey = array_search(end($array), $array);
Аякс

45

чому так складно?

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

Це додасть а, позаду кожного значення, окрім останнього!


2
Ні, якщо наступний вхід $ містить булеве значення false, що є основною проблемою з next ().
soulseekah

29
Якщо я не помиляюся, це не працює, оскільки виклик next () просуває вказівник масиву, тому ви пропускаєте кожен інший елемент у циклі.
Йордан Лев

2
Здається, це не працює для мене. Другий останній елемент не отримує кома, але повинен.
zuallauz

1
Якщо значення дорівнює bool false, воно не працює. Також не друкується остання кома між другим та останнім значенням.
OIS

1
Примітка для всіх, хто хоче використовувати це в PHP7 - вказівник масиву не рухається в циклі foreach, і це не буде працювати.
Скотт Флак

26

Коли 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);

2
Звичайно, вона виконає - $ toEnd для кожної ітерації, ось в чому справа. Якби я перемістив його поза петлею, він більше не працюватиме.
OIS

Найпростіший метод, який коли-небудь застосовувався. $lastValue = array_pop($array);Дякую.
Еліас Ніколя

21

Відповідей уже багато, але варто також розібратися в ітераторах, тим більше що це було запропоновано стандартним способом:

$arr = range(1, 3);

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

Ви можете знайти щось, що робить більш гнучким і для інших випадків.


Чудова відповідь. Я вдячний, що ви використовуєте функції мови, призначені для виконання завдання. i=0;і ++i;завжди здавалися хакітськими мовами сценаріїв, як PHP.
CheddarMonkey

15

Одним із способів може бути виявлення наявності ітератора next. Якщо наступного приєднаного до ітератора немає, це означає, що ви перебуваєте в останньому циклі.

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

Я думаю, що це найпростіший спосіб і вимагає найменшої кількості коду!
привіт ім звайн

1
Не працює з PHP 7+ як "У PHP 7 foreach не використовує внутрішній покажчик масиву."
Демієн Дебін

8

Отже, якщо ваш масив має унікальні значення масиву, то визначення останньої ітерації є тривіальним:

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!';
}

Також відзначте суворий оператор копарізіона, що досить важливо в даному випадку.


це досить неефективний спосіб.
Твій здоровий глузд

Ні. Це не. end () виконує O (1). Він також коротший, ніж інші рішення, і він добре читає -> Якщо елемент дорівнює кінці масиву, напишіть "Останній".
Rok Kralj

Це вдвічі повільніше мого першого та останнього прикладів на 100000 значень.
OIS

5

Припустимо, що у вас масив зберігається в змінній ...

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

Це дуже просто і корисно. Я б порахував масив спочатку поза циклом foreach, щоб програмі не довелося рахувати кожен раз, коли функція foreach оцінює кожен елемент.
Pathros

3
Це не працюватиме на асоціативних масивах. $ ключ - це не завжди число.
Джонатан

5

щоб отримати перший і останній елемент з масиву foreach

foreach($array as $value) {
    if ($value === reset($array)) {
        echo 'FIRST ELEMENT!';
    }

    if ($value === end($array)) {
        echo 'LAST ITEM!';
    }
}

4

Ви все ще можете використовувати цей метод з асоціативними масивами:

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

1
Будь ласка, змініть $ key = $ масив [$ i]; до $ key = $ ключі [$ i]; у першому для циклу.
Нарек

4

Якщо вам потрібно зробити щось для кожного елемента, крім першого чи останнього, і лише якщо в масиві є більше одного елемента, я віддаю перевагу наступному рішенню.

Я знаю, що є багато рішень вище і розміщені місяці / за рік до мого, але це те, що я вважаю досить елегантним саме по собі. Перевірка кожного циклу - це також булева перевірка на відміну від числової "i = (count-1)" чека, яка може передбачати менші накладні витрати.

Структура циклу може здаватися незручною, але ви можете порівняти її з упорядкуванням теда (початок), tfoot (кінець), tbody (поточний) у тегах 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;
}

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

Ви можете сміливо використовувати першу змінну $ для кожного вкладеного циклу, і все буде добре, оскільки кожен цикл робить $ перший помилковим під час першого процесу першої ітерації (тому перерви / винятки не спричинять проблем) .

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

Дякую, це моє улюблене рішення! Це дуже гнучко і коштує лише булева. BTW, я думаю, це буде працювати для масиву, що містить принаймні один елемент (не тільки більше одного елемента).
jc

4

Це повинен бути простий спосіб знайти останній елемент:

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

Довідка: Посилання


- ламане посилання -
T30

3

У мене є сильне відчуття, що в основі цієї "проблеми XY" ОП хотіла просто implode()функціонувати.


1
правда. Бувають випадки, коли імплодес просто не такий практичний. Уявімо, наприклад, що намагаєтеся імплодувати довгий рядок html з великою кількістю динамічних змінних. Звичайно, ви можете зробити ob_start / ob_get_clean на ньому або просто побудувати його як $ str = '...'. Але, бувають випадки, коли це можна вважати просто надмірним
набоєм

3

Оскільки ваш намір знайти масив 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


2

Це здається, що ви хочете щось подібне:

$array = array(
    'First',
    'Second',
    'Third',
    'Last'
);

foreach($array as $key => $value)
{
    if(end($array) === $value)
    {
       echo "last index!" . $value;
    }
}

2
Використання значення зазвичай не є хорошою ідеєю, оскільки воно не працюватиме належним чином, якщо масив має два однакових значення.
orrd

2

Не додайте кому після останнього значення:

Масив:

$data = ['lorem', 'ipsum', 'dolor', 'sit', 'amet'];

Функція:

$result = "";
foreach($data as $value) {
    $resut .= (next($data)) ? "$value, " : $value;
}

Результат:

print $result;

lorem, ipsum, dolor, sit, amet


1

ви можете зробити підрахунок ().

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

або якщо ви шукаєте ТІЛЬКИ останній елемент, ви можете використовувати end ().

end(arr);

повертає лише останній елемент.

і, як виявляється, ви МОЖЕТЕ індексувати масиви php цілими числами. Це цілком задоволено

arr[1];

1
Недолік в кінці (arr) полягає в тому, що він встановлює внутрішній покажчик масиву на останній елемент ..
Vijay

Ні, ви не повинні використовувати цілі числа для доступу до масивів, якщо ви не знаєте, що ключі є цифровими та послідовними. Розглянемо: $a = array(0=>'A', 2=>'B', 'aaa'=>'C'). Що ви отримуєте, якщо отримуєте доступ $a[count($a)-1]?
johndodo

1

Ви також можете зробити щось подібне:

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

     // more code
}

end повертає значення не масиву, тому те, як ви його зробили, не працює. Порівняння рядків також повільніше, ніж ціле.
OIS

Ти правий. він повинен бути кінцевим ($ елементів); $ endKey = ключ ($ елементів);
KOGI

1

Мені подобається таке, як я вважаю, це досить акуратно. Припустимо, ми створюємо рядок з роздільниками між усіма елементами: наприклад, a, b, c

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

зробити це більш простим, не оголошуючи $ перший; використовувати foreach ($ items як $ key => $ item), то $ str = ($ key == 0)?
Мілан Рілекс Рістік


0

Ось ще один спосіб, як ви могли це зробити:

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

0

Якщо я вас зрозумів, то все, що вам потрібно, це повернути масив і отримати останній елемент за допомогою поп-команди:

   $rev_array = array_reverse($array);

   echo array_pop($rev_array);

0

Ви можете також спробувати це зробити, щоб ваш запит ... показаний тут за допомогою 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;
?>

0

Для створення 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 мілісекунд


0

Ще один спосіб - запам'ятати результат попереднього циклу циклу і використовувати його як кінцевий результат:

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

0

Я особисто використовую таку конструкцію, яка дозволяє легко використовувати елементи 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;
}


0
<?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;?>

0

Ось моє рішення: Просто отримайте кількість вашого масиву, мінус 1 (оскільки вони починаються з 0).

$lastkey = count($array) - 1;
foreach($array as $k=>$a){
    if($k==$lastkey){
        /*do something*/
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.