У меня есть цикл 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. Чтобы избежать этого, либо:
$next
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]]; } }