Получить следующий элемент в цикле foreach

У меня есть цикл foreach, и я хочу посмотреть, есть ли в цикле следующий элемент, поэтому я могу сравнить текущий элемент со следующим. Как я могу это сделать? Я читал о текущих и следующих функциях, но я не могу понять, как их использовать.

заранее спасибо

Единственным подходом было бы обратить вспять массив, а затем цикл. Это будет работать и для массивов с неполной индексацией:

$items = array( 'one' => 'two', 'two' => 'two', 'three' => 'three' ); $backwards = array_reverse($items); $last_item = NULL; foreach ($backwards as $current_item) { if ($last_item === $current_item) { // they match } $last_item = $current_item; } 

Если вы все еще заинтересованы в использовании current и next функций, вы можете сделать это:

 $items = array('two', 'two', 'three'); $length = count($items); for($i = 0; $i < $length - 1; ++$i) { if (current($items) === next($items)) { // they match } } 

# 2, вероятно, лучшее решение. Примечание: $i < $length - 1; остановит цикл после сравнения двух последних элементов массива. Я помещал это в цикле, чтобы быть явным с примером. Вероятно, вы должны просто вычислить $length = count($items) - 1;

Вероятно, вы можете использовать цикл while вместо foreach:

 while ($current = current($array) ) { $next = next($array); if (false !== $next && $next == $current) { //do something with $current } } 

Как указывает php.net/foreach :

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

Другими словами – не очень хорошая идея делать то, что вы просите. Возможно, было бы неплохо поговорить с кем-то о том, почему вы пытаетесь это сделать, посмотрите, есть ли лучшее решение? Не стесняйтесь спрашивать нас в ## PHP на irc.freenode.net, если у вас нет других доступных ресурсов.

Если индексы постоянны:

 foreach($arr as $key => $val){ if(isset($arr[$key+1])){ echo $arr[$key+1]; // next element }else{ //end of array reached } } 

если его числовое индексирование:

 foreach ($foo as $key=>$var){ if($var==$foo[$key+1]){ echo 'current and next var are the same'; } } 

Вы можете получить ключи массива перед foreach, а затем использовать счетчик, чтобы проверить следующий элемент, например:

 //$arr is the array you wish to cycle through $keys = array_keys($arr); $num_keys = count($keys); $i = 1; foreach ($arr as $a) { if ($i < $num_keys && $arr[$keys[$i]] == $a) { // we have a match } $i++; } 

Это будет работать как для простых массивов, таких как array(1,2,3) , так и массивы с ключами, такие как array('first'=>1, 'second'=>2, 'thrid'=>3) .

Общее решение может быть итератором кэширования. Правильно реализованный итератор кэширования работает с любым Iterator и сохраняет память. PHP SPL имеет CachingIterator , но он очень странный и имеет очень ограниченную функциональность. Тем не менее, вы можете написать свой собственный итератор lookahead следующим образом:

 <?php class NeighborIterator implements Iterator { protected $oInnerIterator; protected $hasPrevious = false; protected $previous = null; protected $previousKey = null; protected $hasCurrent = false; protected $current = null; protected $currentKey = null; protected $hasNext = false; protected $next = null; protected $nextKey = null; public function __construct(Iterator $oInnerIterator) { $this->oInnerIterator = $oInnerIterator; } public function current() { return $this->current; } public function key() { return $this->currentKey; } public function next() { if ($this->hasCurrent) { $this->hasPrevious = true; $this->previous = $this->current; $this->previousKey = $this->currentKey; $this->hasCurrent = $this->hasNext; $this->current = $this->next; $this->currentKey = $this->nextKey; if ($this->hasNext) { $this->oInnerIterator->next(); $this->hasNext = $this->oInnerIterator->valid(); if ($this->hasNext) { $this->next = $this->oInnerIterator->current(); $this->nextKey = $this->oInnerIterator->key(); } else { $this->next = null; $this->nextKey = null; } } } } public function rewind() { $this->hasPrevious = false; $this->previous = null; $this->previousKey = null; $this->oInnerIterator->rewind(); $this->hasCurrent = $this->oInnerIterator->valid(); if ($this->hasCurrent) { $this->current = $this->oInnerIterator->current(); $this->currentKey = $this->oInnerIterator->key(); $this->oInnerIterator->next(); $this->hasNext = $this->oInnerIterator->valid(); if ($this->hasNext) { $this->next = $this->oInnerIterator->current(); $this->nextKey = $this->oInnerIterator->key(); } else { $this->next = null; $this->nextKey = null; } } else { $this->current = null; $this->currentKey = null; $this->hasNext = false; $this->next = null; $this->nextKey = null; } } public function valid() { return $this->hasCurrent; } public function hasNext() { return $this->hasNext; } public function getNext() { return $this->next; } public function getNextKey() { return $this->nextKey; } public function hasPrevious() { return $this->hasPrevious; } public function getPrevious() { return $this->previous; } public function getPreviousKey() { return $this->previousKey; } } header("Content-type: text/plain; charset=utf-8"); $arr = [ "a" => "alma", "b" => "banan", "c" => "cseresznye", "d" => "dio", "e" => "eper", ]; $oNeighborIterator = new NeighborIterator(new ArrayIterator($arr)); foreach ($oNeighborIterator as $key => $value) { // you can get previous and next values: if (!$oNeighborIterator->hasPrevious()) { echo "{FIRST}\n"; } echo $oNeighborIterator->getPreviousKey() . " => " . $oNeighborIterator->getPrevious() . " -----> "; echo "[ " . $key . " => " . $value . " ] -----> "; echo $oNeighborIterator->getNextKey() . " => " . $oNeighborIterator->getNext() . "\n"; if (!$oNeighborIterator->hasNext()) { echo "{LAST}\n"; } } 

Цикл foreach в php будет перебирать копию исходного массива, делая функции next() и prev() бесполезными. Если у вас есть ассоциативный массив и вам нужно получить следующий элемент, вы можете вместо этого перебирать ключи массива:

 foreach (array_keys($items) as $index => $key) { // first, get current item $item = $items[$key]; // now get next item in array $next = $items[array_keys($items)[$index + 1]]; } 

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

Имейте в виду, что $next будет null для последней итерации, так как после последнего не будет следующего элемента. Доступ к несуществующим клавишам массива вызовет уведомление php. Чтобы избежать этого, либо:

  1. Проверьте последнюю итерацию перед назначением значений $next
  2. Проверьте, существует ли ключ с index + 1 с array_key_exists()

Используя метод 2, полный foreach может выглядеть так:

 foreach (array_keys($items) as $index => $key) { // first, get current item $item = $items[$key]; // now get next item in array $next = null; if (array_key_exists($index + 1, array_keys($items))) { $next = $items[array_keys($items)[$index + 1]]; } }