@GogenZZo

Режим работы из массива в одну строку?

Здравствуйте. Бьюсь над задачей долгое время, никак не могу сообразить =/
Есть массив вида

$arr = [
 ['Пн', '08:00 - 20:00'],
 ['Вт', '08:00 - 20:00'],
 ['Ср', '08:00 - 20:00'],
 ['Чт', '08:00 - 20:00'],
 ['Пт', '08:00 - 20:00'],
 ['Сб', '08:00 - 18:00'],
 ['Вс', '10:00 - 15:00'],
];


Необходимо на выходе получить строку:

Пн-Пт: 08:00 - 20:00, Сб: 08:00 - 18:00, Вс: 10:00 - 15:00
  • Вопрос задан
  • 192 просмотра
Решения вопроса 1
miraage
@miraage
Старый прогер
<?php

$inputs = [
  [
    ['Пн', '08:00 - 20:00'],
    ['Вт', '08:00 - 20:00'],
    ['Ср', '08:00 - 20:00'],
    ['Чт', '08:00 - 20:00'],
    ['Пт', '08:00 - 20:00'],
    ['Сб', '08:00 - 18:00'],
    ['Вс', '10:00 - 15:00'],
  ],

  [
    ['Пн', '08:00 - 19:00'],
    ['Вт', '08:00 - 19:00'],
    ['Ср', '08:00 - 21:00'],
    ['Чт', '08:00 - 20:00'],
    ['Пт', '08:00 - 20:00'],
    ['Сб', '08:00 - 18:00'],
    ['Вс', '10:00 - 15:00'],
  ],
];

function is_consecutive(array $numbers)
{
  $count = count($numbers);

  if ($count < 2) {
    return false;
  }

  $first = $numbers[0];
  $range = range($first, $first + $count - 1);

  return $numbers === $range;
}

function format_day_times(array $input)
{
  $timeIndexes = [];

  foreach ($input as $index => list($day, $time)) {
    $timeIndexes[$time][] = [$index, $day];
  }

  $result = [];

  foreach ($timeIndexes as $time => $data) {
    if (is_consecutive(array_column($data, 0))) {
      $result[] = sprintf(
        '%s-%s: %s',
        $data[0][1],
        array_slice($data, -1)[0][1],
        $time
      );
    } else {
      foreach ($data as list(, $day)) {
        $result[] = sprintf('%s: %s', $day, $time);
      }
    }
  }

  return join(', ', $result);
}

foreach ($inputs as $input) {
  echo format_day_times($input), PHP_EOL;
}


Пн-Пт: 08:00 - 20:00, Сб: 08:00 - 18:00, Вс: 10:00 - 15:00
Пн-Вт: 08:00 - 19:00, Ср: 08:00 - 21:00, Чт-Пт: 08:00 - 20:00, Сб: 08:00 - 18:00, Вс: 10:00 - 15:00
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@Mercury13
Программист на «си с крестами» и не только
Скажем прямо: данная конструкция работает только если выходные дни в начале или конце недели. Если в середине — придётся расширять алгоритмы, да и труднолокализуема (языковые строки одновременно служат техническими ключами).

Заводим три переменных: firstDay, lastDay, workHours. Поначалу они пустые строки.
Проходимся по всем элементам.
• Если рабочие часы совпадают с workHours — перезаписываем lastDay, и всё.
• А если нет — проводим функцию dump, перезаписываем все три.
После цикла принудительно проводим dump.

Как должна работать функция dump.
• Если workHours пусто — ничего не делаем.
• Если результирующая строка непуста — добавляем разделитель.
• В зависимости от того, совпадают ли firstDay и lastDay, добавляем «Пн» или «Пн-Пт».
• Ну и, наконец, добавляем рабочие часы.
Ответ написан
Комментировать
AnnTHony
@AnnTHony
Интроверт
$arr = [
 ['Пн', '08:00 - 20:00'],
 ['Вт', '08:00 - 20:00'],
 ['Ср', '08:00 - 20:00'],
 ['Чт', '08:00 - 20:00'],
 ['Пт', '08:00 - 20:00'],
 ['Сб', '08:00 - 18:00'],
 ['Вс', '10:00 - 15:00'],
];

$res = "";
$i = 0;

do {
	$j = $i + 1;
	do {
		if ($arr[$i][1] <> $arr[$j][1]) {
			break;
		}
		$j++;
	} while ($j < count($arr));
	
	if (strlen($res) > 0) {
		$res .= ", ";
	}
	
	if ($i == $j - 1) {
		$res .= $arr[$i][0] . ": " . $arr[$i][1];
	}
	else {
		$res .= $arr[$i][0] . '-' . $arr[$j - 1][0] . ': ' . $arr[$i][1];
	}
	
	$i = $j;
} while ($i < count($arr));

echo $res;
Ответ написан
Комментировать
Rastishka
@Rastishka
А в чем проблема, какой у вас код? Бежим циклом, по исходному массиву, генерируем новый массив:

Если предыдущее время работы != последнему добавленному,
добавляем строку в новый массив,
иначе
модифицируем последний элемент нового массива (добавляем новый день недели).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы