Извлечь элементы из следующего элемента foreach в PHP?

Я делаю систему предупреждений в стиле PHP "светофор" для своего веб-сайта, которая в основном говорит: "Если между текущей записью массива и следующей будет X процентное изменение, выведите ошибку".

Итак, я перебираю элементы массива в цикле foreach, однако нужно иметь возможность сделать что-то вроде этого: (примечание: это только базовый пример, но должно быть достаточно, чтобы понять идею)

foreach($array as $a)
{
$thisValue = $a['value'];
$nextValue = next($a['value']);

$percentageDiff = ($nextValue-$thisValue)/$thisValue;
}

Я добавил теги next(), чтобы получить следующее значение, но понимаю, что это работает только для массивов. Есть ли что-то еще, что я могу использовать, чтобы получить следующий элемент foreach?

Спасибо за ваше время!

8 ответов

Решение

Сделайте это по-другому, сохраните предыдущую запись и сравните их.

$prev = null;
foreach ($item as $i){
    if ($prev !== null){
        diff($prev, $i);
    }
    $prev = $i
}

Простой ответ: не используйте foreach петля. Используйте простой for цикл вместо:

for ($i = 0; $i < count($array); $i++) {
    if (isset($array[$i + 1])) {
        $thisValue = $array[$i]['value'];
        $nextValue = $array[$i + 1]['value'];

        $percentageDiff = ($nextValue-$thisValue)/$thisValue;
    }
}

Если вы хотите работать с foreachВы можете сравнить текущее значение с предыдущим значением вместо следующего значения:

$previous = null;
foreach ($array as $a) {
    if (!is_null($previous)) {
        $thisValue = $previous['value'];
        $nextValue = $a['value'];
        $percentageDiff = ($nextValue-$thisValue)/$thisValue;
    }
    $previous = $a;
}

При этом вы просто сдвигаете всю итерацию на один элемент.

Вы должны быть в состоянии использовать:

foreach($array as $a)
{
    $array_copy = $array;
    $thisValue = $a['value'];

    $nextValue = next($array_copy);
    $nextValue = $nextValue['value'];

    $percentageDiff = ($nextValue-$thisValue)/$thisValue;
}

Это копирует массив и затем перемещает указатель вперед на 1.

Самое простое решение IMO - изменить свое мышление. Вместо проверки текущей и следующей записи, проверьте предыдущую и текущую запись. Помнить предыдущий легче, чем получить следующий.

Если вы не хотите этого, вы также можете отказаться от foreach и итерации в стиле C, используя for и переменная-счетчик - хотя бы один недостаток: разреженные массивы PHP могут укусить вас, так что лучше всего позвонить array_values() на проверяемом массиве перед итерацией.

"Обычно проще использовать предыдущее значение, чем следующее:

$lastValue = NULL;
foreach ($array as $a) {
    if ($lastValue === NULL) {
        $lastValue = $a['value'];
        continue;
    }

    $percentageDiff = ($a['value'] - $lastValue) / $lastValue;

    $lastValue = $a['value'];
}
for($i=0;$i<count($array);$i++) {
$thisValue = $array[$i];
$nextValue = $array[i+1]; // will not be set if $i==count($array)-1
$percentageDiff = ($nextValue-$thisValue)/$thisValue;
}

Действительно, есть функции- итераторы массива, которые поддерживают то, что вам нужно, а также просто зацикливают массив с помощью next() / prev() и т. Д., Работает нормально, но решение выше более элегантно

Это не работает с foreach, потому что foreach создает копию ссылок и не устанавливает указатели массива в самом массиве.

Вот пример, который можно использовать для ассоциативных массивов с использованием функций итераторов массива:

$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();

        for($i=0;$i<count($array);$i++) {
           $iterator->seek($i);
           $thisValue = $iterator->current();
           $iterator->seek($i+1);
           $nextValue = $iterator->current(); 
           $percentageDiff = ($nextValue-$thisValue)/$thisValue;
        }

Почему бы просто не использовать обычный цикл for, а не итератор foreach?

<?php
    $testArray = array(10,20,30,40,50,60,70,80,90,100);

    $elementCount = count($testArray);
    for($loop=0; $loop<$elementCount; $loop++) {

        $thisValue = $testArray[$loop];

        // Check if there *is* a next element.
        $nextValue = $loop + 1 < $elementCount ? $testArray[$loop + 1] : null;

        // Calculate the percentage difference if we have a next value.
        if($nextValue) $percentageDiff = ($nextValue-$thisValue)/$thisValue;
    }
?>
Другие вопросы по тегам