Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Вы могли бы использовать цикл while вместо foreach:

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

Ответ 3

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

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

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

Ответ 4

Если индексы непрерывны:

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

Ответ 5

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

foreach ($foo as $key=>$var){

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

Ответ 6

Общее решение может быть итератором кеширования. Правильно реализованный итератор кэширования работает с любым 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";
    }
}

Ответ 7

Вы можете получить ключи массива перед 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).

Ответ 8

Цикл 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]];
    }
}

Ответ 9

Вы можете получить ключи/значения и индекс

<?php
$a = array(
    'key1'=>'value1', 
    'key2'=>'value2', 
    'key3'=>'value3', 
    'key4'=>'value4', 
    'key5'=>'value5'
);

$keys = array_keys($a);
foreach(array_keys($keys) as $index ){       
    $current_key = current($keys); // or $current_key = $keys[$index];
    $current_value = $a[$current_key]; // or $current_value = $a[$keys[$index]];

    $next_key = next($keys); 
    $next_value = $a[$next_key] ?? null; // for php version >= 7.0

    echo  "{$index}: current = ({$current_key} => {$current_value}); next = ({$next_key} => {$next_value})\n";
}

результат:

0: current = (key1 => value1); next = (key2 => value2) 
1: current = (key2 => value2); next = (key3 => value3) 
2: current = (key3 => value3); next = (key4 => value4) 
3: current = (key4 => value4); next = (key5 => value5) 
4: current = (key5 => value5); next = ( => )