<rmcreative>

RSS

PHP: последний элемент foreach. Альтернативнвый вариант.

3 апреля 2008

Один вариант уже был (для сравнения его тоже приведу), теперь ещё один:

foreach ($array as $key => $value) {
  if($value == end($array)) {
        // делаем что-либо с последним элементом...
  }
  else {
        // делаем что-либо с каждым элементом
  }
}

Вариант Kost

foreach ($array as $key => $value) {
   if (!next($array)) {
        // делаем что-либо с последним элементом...
   }
   else {
       // делаем что-либо с каждым элементом
   }
}

edit1:

Спасибо dkrnl. Устроил тест.

Вариант №1 работает только если явно задать ключи:

$array = array('1' => '1','2' => '2','3' => '3', '4'=>'4','5'=>'5');

Вариант №2 работает только если массив передать по ссылке:

$array = new ArrayObject(array(1,2,3,4,5));

Работающий в любом случае вариант:

$total = count($array);
$counter = 0;
foreach($array as $key => value){
  $counter++;
  if($counter == $total){
    // делаем что-либо с последним элементом...
  }
  else{
    // делаем что-либо с каждым элементом
  }
}

edit2:

А ведь и правда стало смахивать на for :) Неудобство в том, что при обращении к элементу в случае с for придётся использовать индекс.

edit3:

Неплохое решение DeadLy:

$end_element = array_pop($array);
foreach ($array as $value) {
   // делаем что-либо с каждым элементом
}
   // делаем что-либо с последним элементом $end_element

Комментарии RSS

  1. №115
    dkrnl
    dkrnl 03 апр. 2008 г., 13:29:01

    это не рабочий код - внутри foreach нельзя перемешать(reset,end,next...) внутренний указатель перебираемого массива.

  2. №116
    mAd
    mAd 03 апр. 2008 г., 13:36:45

    Да, кое-где работает, но не желательно такое использовать, не на всех серверах сработает

  3. №117
    Sam
    Sam 03 апр. 2008 г., 14:19:38

    dkrnl

    Попробуйте.

    mAd

    И как это зависит от сервера?

  4. №118
    dkrnl
    dkrnl 03 апр. 2008 г., 14:55:34

    код:

    echo "php: ", PHP_VERSION;
     
    echo "<hr>";
     
    echo "v1:<br>";
    $array = array(1,2,3,4,5);
    foreach ($array as $key => $value) 
    {
      echo $value;
      if($key != end($array))
      {
        echo ", ";
      }
    } 
     
    echo "<hr>";
     
    echo "v2:<br>";
    foreach ($array as $key => $value) 
    {
      echo $value;
      if (next($array)) 
      {
        echo ", ";
      }
    }

    результат:

    php: 5.2.4


    v1:

    1, 2, 3, 4, 5,


    v2:

    1, 2, 3, 45

    В первом случаи все безтолку, во втором внутрений указатель "калбасит".

  5. №119
    dkrnl
    dkrnl 03 апр. 2008 г., 15:02:07

    про end:

    mixed end ( array &$array )

    end() устанавливает внутренний указатель array на последний элемент и возвращает его значение.

    про next:

    mixed next ( array &$array )

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

    про foreach:

    Замечание: When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.

    Замечание: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.

  6. №120
    Sam
    Sam 03 апр. 2008 г., 15:51:00

    Да, дествительно...

    Вариант №1 работает только если явно задать ключи:

    $array = array('1' => '1','2' => '2','3' => '3', '4'=>'4','5'=>'5');

    Вариант №2 работает только если массив передать по ссылке:

    $array = new ArrayObject(array(1,2,3,4,5));

    Работающий в любом случае вариант:

    $total = count($array);
    $counter = 0;
    foreach ($array as $key => value){
        $counter++;
        if ($counter == $total){
            // делаем что-либо с последним элементом...
       } else {
            // делаем что-либо с каждым элементом
       }
    }
  7. №123
    Денис Радченко
    Денис Радченко 03 апр. 2008 г., 17:55:27

    Если нужно знать последний элемент массива, то лучше через for сделать

  8. №124
    Sam
    Sam 03 апр. 2008 г., 18:13:38

    Ну, на самом деле да :)

  9. №125
    Sam
    Sam 03 апр. 2008 г., 18:19:21

    Хотя придётся указывать индексы...

  10. №126
    mAd
    mAd 03 апр. 2008 г., 19:22:50

    "И как это зависит от сервера?"

    сужу только по своему опыту

    Делал так в одном из проектов, локально работало, на хостинге фирмы тоже работало, залили на хостинг заказчика перестало работать, не end не next в foreach корректно не работал. причину выяснять времени небыло, быстрее было переписать на for.

  11. №127
    Sam
    Sam 03 апр. 2008 г., 19:38:34

    Ну, скорее это зависило от версии PHP, нежели от сервера. Вообще, как видно, вприанты с for и счётчиком - единственные стабильные из рассмотренных.

  12. №134
    DeadLy
    DeadLy 04 апр. 2008 г., 9:51:29
    $end_element = array_pop($array);
     
    foreach ($array as $value) {
     
    // делаем что-либо с каждым элементом
     
    }
     
    // делаем что-либо с последним элементом...
  13. №136
    Sam
    Sam 04 апр. 2008 г., 13:15:54

    Ну, это не совсем то: нам нужно сделать с последним что-то уникальное. Допустим, вывести все на печать с запятой, а последний - с точкой.

  14. №137
    DeadLy
    DeadLy 04 апр. 2008 г., 14:07:52

    Почему же не то?

    $array = array(1,2,3);
     
    $end_element = array_pop($array);
     
    foreach ($array as $value) {
     
     echo $value.' - !';
     
    }
     
     echo $end_element.' - Последний элемент';
  15. №138
    Sam
    Sam 04 апр. 2008 г., 14:11:49

    Извиняюсь, перепутал array_pop с end :) Хорошее решение. Добавлю к основной заметке.

  16. №139
    DeadLy
    DeadLy 04 апр. 2008 г., 14:16:29

    а вообще если просто вывести 1,2,3,4,5

    то можно

    $values = '1,2,3,4,5,'; // результат работы foreach
     
    $values = substr($values,0,-1); 
     
    echo $values; //результат 1,2,3,4,5
  17. №445
    Psih
    Psih 17 июля 2008 г., 17:54:09

    Эмм, народ, вы меня умиляете.

    Есть два простейших способа.

    Первый заключается в том, что бы генерировать листинг тагов зарание правильно:

    $tag_list = Array();
     
    foreach ($someDataSource as $item) {
     
     // code here
     
     $tag_list[] = $item['someTagData']
     
    }
     
    $tag_list = implode(',', $tag_list);
     
    echo $tag_list; // tag1, tag2, ...., tagN

    Второй, когда уже имеем готовую строку:

    $str = 'tag1, tag2, ..., tagN,';
     
    $str = trim($str, ',');
  18. №446
    nix
    nix 17 июля 2008 г., 17:54:39
    echo join(', ', $array)
  19. №449
    Psih
    Psih 17 июля 2008 г., 17:58:02

    nix

    http://lv.php.net/manual/ru/function.join.php

    join — Псевдоним функции implode()

  20. №450
    Sam
    Sam 17 июля 2008 г., 18:24:10

    Psih

    За напоминание о join спасибо.

    Список тэгов — всего лишь пример. Задача — исключительно обработать последний элемент массива.

  21. №471
    Artur
    Artur 24 июля 2008 г., 11:28:10

    А можно просто использовать implode или explode Где разделитель ", "

    :-))

    Удачи!

  22. №5164
    Кирилл
    Кирилл 11 авг. 2011 г., 12:22:32

    У вас в первом примере в условии 1 скобки не хватает.
    PS. Извиняюсь за некропост, просто решение искал и на ваш блог наткнулся ;)

  23. №5169
    Sam
    Sam 11 авг. 2011 г., 19:18:32

    Кирилл, поправил, спасибо.

  24. №6680
    eriks
    eriks 19 сент. 2012 г., 6:05:36

    Не поможет implode когда разделителем станет не запятушечка, а некий код. Тут уже надо какой-нить count приделывать. Типа:

    $count = count($array);
    foreach ($array as $key => $val) {
      // Что-то основное
      if ($key != $count) {
        // Что-то разделительное
      }
    }

    Ну, а уж если ключи вас беспокоят, то:

    $count = count($array);
    foreach ($array as $val) {
      // Что-то основное
      if (--$count > 0) {
        // Что-то разделительное
      }
    }
  25. №8720
    Asiro
    Asiro 30 дек. 2013 г., 16:54:41
    $arrEndVal = end($arr) || $arr[count($data)-1];
    foreach($arr as $k => $v){
        // что-то делаем, если последний элемент массива.
        if($arrEndVal === $v){
        } else{
        }
    }
  26. №9845
    Сергей
    Сергей 13 июня 2015 г., 10:29:05

    Что-то никто за 7 лет не вспомнил про key(), так что я тут тоже понекропощу :)

    end($array);
    $array[key($array)] = "It's a last element";
  27. №9985
    reinq
    reinq 09 сент. 2015 г., 11:52:01

    Предлагаю опубликовать это сниппетом на gostash.it

  28. №9986
    Sam
    Sam 09 сент. 2015 г., 14:02:27

    reinq, готово.

  29. №10352
    Катрчиенко Денис
    Катрчиенко Денис 13 марта 2016 г., 7:30:17

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

    foreach($array as $v){
    if (count($array) == $i++ ) {
     // что-то делаем, если последний элемент массива. 
    }else{
     // что-то делаем, не последний )
    }
    }

    саму count естественно лучше использовать до цикла, для повышения производительности. Но я думаю смысл всем ясен)

  30. №10567
    Дмитрий
    Дмитрий 04 июля 2016 г., 14:01:03
    foreach($array as $val){
      $output .= strlen($output) > 0 ? '' : 'последний элемент';
      $output .= $val;
    }
    
  31. №11037
    Дмитрий
    Дмитрий 05 июля 2017 г., 14:59:28

    Ребят, я реализовываю в своих проектах это дело так -

    {foreach items as key = value}
    <?php echo count($items) == $key+1 ? "hidden-sm":"col-sm-6"; ?>
    // Здесь идет какой-то код вывода данных типа - {value[price]}
    </div>
    {/foreach}

    Ну разумеется - тут логика понятна? Это я просто шаблонизатор еще использую)

    Кстати, админ - нажимаю на кнопку "код" - ни ответа, ни привета :D

  32. №11039
    Sam
    Sam 12 июля 2017 г., 14:22:53

    Дмитрий, да, кнопочки отломались. Пора переписать...

  33. №11061
    Сергей
    Сергей 19 авг. 2017 г., 23:48:57

    Хочется и свои 5 копеек вставить, ибо тут прям неплохо описаны советы, хорошая подборка. Самый лайфаковый метод был от DeadLy, но это довольно не хорошо в плане кода. Так вот, у меня проблема была - что в массивах может быть что угодно - гипер-вложенные массивы, огромных размеров, и при этом значения всевозможные, в том числе и null. Конечно самый простой, надёжный и универсальный способ это - for. Но для форыча, я немного дополнил под свою задачу один из ваших вариантов (слава пользователю Kost!) и сделал следующую конструкцию:

    if(!next($array) && !key($array)){
       ...что-то делаем с последним 
    }
  34. №11300
    acid
    acid 28 авг. 2018 г., 14:22:56

    Ребзя, я так делаю:

    foreach(...)
    {
       if(@$i++ == 0) ...
    }
  35. №11301
    acid
    acid 28 авг. 2018 г., 14:24:52

    Кстати можно и:

    if (!@$i++) ...

    :)

  36. №11347
    Влад
    Влад 27 сент. 2018 г., 17:04:29

    Зачем каунтер если есть $key в цикле?

  37. №11368
    Андрей
    Андрей 05 дек. 2018 г., 17:46:48

    В первом решении ошибка. End возвращает не ключ, а значение. Вот и сравнивать нужно с ним.

    if($value== end($array)) {
  38. №11369
    Sam
    Sam 06 дек. 2018 г., 18:40:52

    Андрей, поправил. Спасибо.

  39. №11521
    Андрей С.
    Андрей С. 24 июня 2019 г., 13:06:45
    if($value== end($array)) {

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

    Например: ["название", "стоимость", "базовая валюта", "количество", "общая сумма", "валюта расчета"]

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

  40. №11953
    Дмитрий
    Дмитрий 11 сент. 2020 г., 21:16:06

    Работает! В закладки.

  41. №12149
    Кирилл
    Кирилл 24 марта 2021 г., 9:41:20

    foreach($arr as $key => $value){ if($key == array_key_last($arr)) ... else ... }

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.