@tohin15

Как реализовать алгоритм группировки массива по значению?

Есть массив с днями недели и часами работы
$openingHours = [
            ['day' => 'monday', 'time' => '08:00-20:00'],
            ['day' => 'tuesday', 'time' => '08:00-20:00'],
            ['day' => 'wednesday', 'time' => '08:00-20:00'],
            ['day' => 'thursday', 'time' => '10:00-20:00'],
            ['day' => 'friday', 'time' => '10:00-18:00'],
            ['day' => 'saturday', 'time' => '10:00-16:00'],
            ['day' => 'sunday', 'time' => '10:00-16:00'],
        ];

Необходимо сгруппировать его так, чтобы дни с одинаковыми часами работы объединялись в один элемент. Примерно так
$result = [
            'monday - wednesday' => '08:00-20:00',
            'thursday' => '10:00-20:00',
            'friday' => '10:00-18:00',
            'saturday - sunday' => '10:00-16:00',
        ];

Как этого можно добиться? Спасибо!
  • Вопрос задан
  • 965 просмотров
Решения вопроса 1
GomelHawk
@GomelHawk
PHP / Symfony developer
Если предположить, что дни недели упорядочены по возрастанию, то можно использовать что-нибудь такое:

$openingHours = [
    ['day' => 'monday', 'time' => '08:00-20:00'],
    ['day' => 'tuesday', 'time' => '08:00-20:00'],
    ['day' => 'wednesday', 'time' => '08:00-23:59'],
    ['day' => 'thursday', 'time' => '08:00-20:00'],
    ['day' => 'friday', 'time' => '08:00-20:00'],
    ['day' => 'saturday', 'time' => '10:00-16:00'],
    ['day' => 'sunday', 'time' => '10:00-16:00'],
];

$result = $active = [];

$openingHours[] = ['day' => '', 'time' => '']; // empty value to simplify code

foreach ($openingHours as $openingHour) {
    if ($active) {
        if ($active['time'] === $openingHour['time']) {
            $active['end'] = $openingHour['day'];
        } else {
            $key          = $active['end'] ? $active['start'] . '-' . $active['end'] : $active['start'];
            $result[$key] = $active['time'];
            $active       = [];
        }
    }
    $active = $active ?: [
        'time'  => $openingHour['time'],
        'start' => $openingHour['day'],
        'end'   => null,
    ];
}

print_r($result);
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Vlad_IT
@Vlad_IT
Front-end разработчик
Решение в лоб: создаете ассоциативный массив, где ключ - время, значение - массив дней недели. И просто проходите каждый элемент $openingHours, берете с него время, проверяете, есть ли оно в нашем созданном массиве, если нет, создаем и добавляем туда день, если есть, то просто добавляем туда день.
Ну, потом уже пишите функцию, которая преобразует наш созданный массив в тот, что вам нужно. Это тоже довольно просто, смотрим ключ, берем его значения, соединяем их через разделитель -, и используем как ключ в новом массиве.
Ответ написан
Eridani
@Eridani
Мимо проходил
Если по замыслу Владимир Проскурин
$openingHours = [
            ['day' => 'monday', 'time' => '08:00-20:00'],
            ['day' => 'tuesday', 'time' => '08:00-20:00'],
            ['day' => 'wednesday', 'time' => '08:00-20:00'],
            ['day' => 'thursday', 'time' => '10:00-20:00'],
            ['day' => 'friday', 'time' => '10:00-18:00'],
            ['day' => 'saturday', 'time' => '10:00-16:00'],
            ['day' => 'sunday', 'time' => '10:00-16:00'],
        ];
$temp = array();
$result = array();

foreach($openingHours as $key => $item) {
  $temp[$item['time']][] = $item['day']; 
}
foreach($temp as $key => $item){
  $count = count($item) -1;
  $count >= 1 ? $result[$item[0].'-'.$item[$count]] = $key : $result[$item[0]] = $key; 
}
print_r($result);


Array
(
    [monday-wednesday] => 08:00-20:00
    [thursday] => 10:00-20:00
    [friday] => 10:00-18:00
    [saturday-sunday] => 10:00-16:00
)


P.S. На другие реализации или упрощение вышеописанного и сам с удовольствием посмотрю
Ответ написан
pligin
@pligin
быдлокодер
В итоге получается массив с днями недели в упорядоченном виде. Осталось только придумать функцию, которая определит, что дни идут подряд без перерыва и ставить "тире", иначе запятую. Это на телефоне писал))) Как буду у компьютера, додумаю
$openingHours = [
            ['day' => 'tuesday', 'time' => '08:00-20:00'],
            ['day' => 'wednesday', 'time' => '08:00-20:00'],
            ['day' => 'thursday', 'time' => '10:00-20:00'],
            ['day' => 'friday', 'time' => '10:00-18:00'],
            ['day' => 'saturday', 'time' => '10:00-16:00'],
            ['day' => 'sunday', 'time' => '10:00-16:00'],
            ['day' => 'monday', 'time' => '08:00-20:00'],
        ];
$template = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'];
$new = array();
foreach ($openingHours as $key => $value){
	$new[$value['time']][] = $value['day'];
	$new[$value['time']] = array_intersect($template,$new[$value['time']]);
}
print_r($new);

Array
(
    [08:00-20:00] => Array
        (
            [1] => monday
            [2] => tuesday
            [3] => wednesday
        )

    [10:00-20:00] => Array
        (
            [4] => thursday
        )

    [10:00-18:00] => Array
        (
            [5] => friday
        )

    [10:00-16:00] => Array
        (
            [0] => sunday
            [6] => saturday
        )
)

Ну и ключи у названий дней сохраняются, можно в шаблоне для сортировки добавить ключи от 1 до 7, чтобы в будущем, если пригодится, доставать день недели по ключу (порядковому номеру дня в неделе)
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 05:01
999999 руб./за проект
19 апр. 2024, в 03:52
1000 руб./за проект
19 апр. 2024, в 03:01
1000 руб./за проект