#php #arrays #algorithm
#php #массивы #алгоритм
Вопрос:
У меня есть решение, которое принимает m-element array
возвращает n-element array
равномерно распределенный. Но для некоторого значения m он генерирует stderr
.
Например, если массив будет содержать 15 элементов, то это stderr
будет:
class SpredArrayClass
{
var $array = [1,2,3,4,5,6,7,8,9,9,10,11,12,13,14,15];
function spreadOutArray(array $array = [], $targetOutputLength = 10) {
$array = $this->array;
$originalArrayLength = count($array);
if ($originalArrayLength == 0) {
return false;
}
if ($originalArrayLength <= $targetOutputLength) {
return $array;
}
$output = [];
$interval = round($originalArrayLength / $targetOutputLength);
for ($index = $originalArrayLength - 1; count($output) < $targetOutputLength; $index -= $interval) {
$output[] = $array[$index];
}
return array_reverse($output);
}
}
Проблема, по-видимому, заключается в этой части:
$output = [];
$interval = round($originalArrayLength / $targetOutputLength);
for ($index = $originalArrayLength - 1; count($output) < $targetOutputLength; $index -= $interval) {
$output[] = $array[$index];
}
Undefinded offset stderr
появляется в этой строке: $output[] = $array[$index];
Демонстрация выполнения кода здесь: http://ideone.com/UrF9UK
Комментарии:
1. Когда-нибудь слышали о
range()
?2. Вы могли бы сделать свою жизнь намного проще, используя диапазон php, как правильно намекнул @PHPglue….
3. Похоже, готовится новый экзамен по кодированию или аналогичный. Подобные вопросы с использованием одних и тех же формулировок уже задавались дважды до сегодняшнего дня…
4. Вы не можете использовать фиксированное значение для каждого «шага» ($ interval) и в то же время гарантировать правильную выходную длину.
5. Объясните, что вы подразумеваете под распределением равномерно. An
array_splice()
?
Ответ №1:
Вы округляете слишком рано. Шаги ($interval) должны быть точными, потому что, если округление вверх, шаги приведут вас слишком быстро к началу массива и приведут к отрицательным индексам.
Поэтому округляется только при использовании результирующего индекса:
$interval = $originalArrayLength / $targetOutputLength;
for ($index = $originalArrayLength - 1; count($output) < $targetOutputLength; $index -= $interval) {
$output[] = $array[round($index)];
}
Комментарии:
1. Принятое вами решение не всегда будет возвращать массив с желаемым количеством элементов, но меньше. Если вы запустите его на образце массива, который вы указали в вопросе, в выходном массиве будет только 8 элементов вместо 10. Вам действительно нужно удалить
round
из$interval
: это неправильная арифметика.2. Да, я понял. Вы правы. У меня были дополнительные проблемы с кодом, который я выбрал в качестве решения.
Ответ №2:
Ваша проблема связана с условием в вашем
for
цикле. Измените его на это:
$output = [];
$interval = round($originalArrayLength / $targetOutputLength);
// JUST KEEP LOOPING amp; PUSHING TILL SO LONG AS $index IS GREATER THAN 0;
for($index = $originalArrayLength - 1; $index>=0; $index -= $interval) {
$output[] = $array[$index];
}
Комментарии:
1. Это лучше, потому что он не вызывает round в каждом цикле.