#php #arrays #loops #range #increment
#php #массивы #циклы #диапазон #увеличить
Вопрос:
Учитывая два целых числа (каждое из которых представляет месяцы в году), мне нужно создать массив целых чисел, который представляет инклюзивный диапазон месяцев между ними.
Чтобы получить номера месяцев между декабрем и февралем, входные данные:
$start = 12;
$finish = 2;
Ожидаемый результат содержит три элемента: 12, 1 и 2 (потому что декабрь, январь, затем февраль)
Я пробовал использовать $arraylist = range($start, $finish);
, но когда $start
значение больше $finish
значения, то на выходе получается неправильный диапазон убывания, подобный этому: [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
Вот еще несколько примеров ввода-вывода:
-------- --------- -----------------------
| $start | $finish | $output |
-------- --------- -----------------------|
| 3 | 11 | [3,4,5,6,7,8,9,10,11] |
-------- --------- -----------------------|
| 11 | 3 | [11,12,1,2,3] |
-------- --------- -----------------------|
| 3 | 3 | [3] |
-------- --------- -----------------------
Комментарии:
1. Откуда
1
берется в вашем желаемом выводе?2. @Nick Я создал массив для количества месяцев, с номером метода 2 для ввода, если начало ввода равно 11, а конец равен 3, то получится [11,12,1,2,3]
3. каков ожидаемый результат, когда начало равно 3, а конец равен 3? Один элемент или тринадцать элементов?
4. @mickmackusa bcs — это количество месяцев, я надеюсь, что возвращаемый результат равен 3, если мы вводим 3 и 3 в качестве диапазона
5. Качество ввода недостаточно для выражения нескольких лет — поскольку ожидается, что входное значение будет между 1 и 12. Если у вас (или у кого-либо еще) другие требования к вопросу, не стесняйтесь задать новый вопрос и указать, как требуется новый метод для расширения функциональности представленных здесь решений. Важно, чтобы объем этого вопроса не уходил в небытие. Это хороший, узкий вопрос, и я надеюсь, что так и останется. Я опечален тем фактом, что этот вопрос получил DVS и был закрыт — я думаю, что в этом сообществе слишком много негатива.
Ответ №1:
Это может быть намного проще, чем уменьшение всего, использование модуля / арифметики и приведение чисел к предпочтительному значению.
- Цикл, пока два числа не совпадают.
- Если увеличенное число увеличивается до более чем 12, сбросьте его до 1.
- Чтобы включить диапазон, вставьте конечный номер в массив.
Код (Демо)
$array = [];
while ($start != $finish) {
if ($start > 12) {
$start = 1;
}
$array[] = $start ; // increment AFTER pushing into the array
}
$array[] = $finish;
var_export($array);
Я думаю, что это менее загадочно для чтения.
Входы / выходы:
11, 3: [11, 12, 1, 2, 3]
3, 11: [3, 4, 5, 6, 7, 8, 9, 10, 11]
3, 3: [3]
p.s. Следующий функциональный стиль также не кажется глупым. Будет либо 1, либо 3 вызова функции, но опять же, я думаю, что это довольно легко читать, и в нем нет цикла, временных переменных и увеличения / уменьшения.
Поскольку объем данных гарантированно будет небольшим, производительность, вероятно, даже не учитывается (ни один человек не заметит разницы в производительности между методами на этой странице). Было бы лучше выбрать метод, который доступен для чтения.
Код: (Демо)
$array = $start > $finish
? array_merge(range($start, 12), range(1, $finish))
: range($start, $finish);
p.p.s. Последнее соображение… Если кто-нибудь предпочтет обрабатывать логику месяца с помощью метода DateTime, это также было бы разумно и может открыть дверь для дальнейшего расширения функциональности (если это когда-либо понадобится задаче). Недостатком является то, что этот метод имеет наибольшие накладные расходы, поскольку он создает экземпляры объектов для работы.
Чтобы выходной массив включал последний месяц, простым решением является добавление 1 к концу. Если $begin
значение меньше $finish
значения, то мы перенесем значение на следующий год, добавив 12.
Код: (Демо)
$begin = 11;
$finish = 3;
$period = new DatePeriod(
DateTime::createFromFormat('m', $begin),
new DateInterval('P1M'),
DateTime::createFromFormat('m', $finish ($begin > $finish ? 13 : 1))
);
foreach ($period as $obj) {
$array[] = $obj->format('n');
}
var_export($array);
Ответ №2:
Один из способов сделать это — использовать арифметику по модулю 12. Сначала преобразуйте $start
и $finish
в диапазон 0-11, вычитая единицу, затем увеличьте $start
и переместите в массив (преобразуя обратно в диапазон 1-12, как вы делаете) до $start == $finish
:
$start = 12;
$finish = 2;
$arraylist = array();
$start = --$start;
$finish = --$finish;
while ($start != $finish) {
$arraylist[] = $start;
$start = $start % 12;
}
$arraylist[] = $start;
print_r($arraylist);
Вывод:
Array
(
[0] => 12
[1] => 1
[2] => 2
)