Извлечь элементы из следующего элемента 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;
}
?>