Найти последний элемент массива при использовании цикла foreach в PHP - PullRequest
189 голосов
/ 20 марта 2009

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

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

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

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

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

Ответы [ 31 ]

281 голосов
/ 20 марта 2009

Звучит так, будто вы хотите что-то вроде этого:

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

Как говорится, вы не должны перебирать "массив", используя foreach в php.

188 голосов
/ 20 марта 2009

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

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

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

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

22 голосов
/ 20 марта 2009

Когда 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);
20 голосов
/ 11 октября 2011

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

$arr = range(1, 3);

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

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

12 голосов
/ 18 октября 2017

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

foreach ($some_array as $element) {
    if(!next($some_array)) {
         // This is the last $element
    }
}
8 голосов
/ 21 апреля 2012

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

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

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

5 голосов
/ 09 октября 2012

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

foreach($array as $key=>$value) 
{ 
    echo $value;
    if($key != count($array)-1) { echo ", "; }
}
4 голосов
/ 22 мая 2014

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

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

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

4 голосов
/ 18 марта 2010

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

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

Структура цикла может показаться неудобной, но вы можете сравнить ее с упорядочением thead (начало), 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;
}

Например, в терминах веб-разработки, если вы хотите добавить border-bottom к каждому элементу, кроме последнего в неупорядоченном списке (ul), тогда вы можете вместо этого добавить border -top для каждого элемента, кроме первого (CSS: first-child, поддерживаемый IE7 + и Firefox / Webkit поддерживает эту логику, тогда как: last-child не поддерживается 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...