Многократное пересечение времени в php - PullRequest
1 голос
/ 17 августа 2011

У меня есть ситуация, когда я не могу обернуть голову в данный момент.Несколько временных перекрытий.Я видел много постов в два раза, которые перекрываются , но ничего, что имеет многократное перекрытие.

Вот данные, которые я хотел бы поместить в:

<?php
//RUN EACH Class Selection for Monday
foreach($class as $Classes){
    $time[] = array($ClassStartTime, $ClassEndTime, $classID);
}

OverLapFunction($time);
?>

Который затем разместит classID и Overlapping AmountКто-нибудь сталкивался с такой ситуацией раньше?Или разобрался как это сделать?

Ответы [ 2 ]

3 голосов
/ 17 августа 2011

Скажите, что ваши данные таковы:

$classes = array(
    array(
       'name' => 'A',
       'day'  => 'Monday',
       'start'=> '08:00AM',
       'end'  => '11:00AM',
    ),
    array(
       'name' => 'B',
       'day'  => 'Monday',
       'start'=> '10:00AM',
       'end'  => '11:30AM',
    ),
    array(
       'name' => 'C',
       'day'  => 'Monday',
       'start'=> '12:00PM',
       'end'  => '04:00PM',
    ),
    array(
       'name' => 'D',
       'day'  => 'Monday',
       'start'=> '03:00PM',
       'end'  => '06:00PM',
    ),
);

Вам просто нужно вложенное foreach, вот так:

$overlap = array();
foreach ($classes as $class1) {
    foreach ($classes as $class2) {
        if ($class1['day'] != $class2['day'] || $class1 == $class2) continue;
        if (strtotime($class1['start']) <  strtotime($class2['end']) &&
            strtotime($class1['start']) >= strtotime($class2['start']))
        {
            $array = array($class1['name'], $class2['name']);
            sort($array);
            if (!in_array($array, $overlap)) $overlap[] = $array;
        }
    }
}

По сути, он сравнивает каждый класс со всеми классами. Если $class1 время начала меньше $class2 время окончания и $class1 время начала больше $class2 время начала: они перекрываются. Помните, что каждый класс будет сравниваться друг с другом дважды (например, от А до В, от В до А), поэтому, если он не совпадает на первом проходе, он будет на втором.

Это даст вам:

Array
(
    [0] => Array
        (
            [0] => B
            [1] => A
        )

    [1] => Array
        (
            [0] => D
            [1] => C
        )

)

Если вы измените класс D на:

array(
   'name' => 'D',
   'day'  => 'Monday',
   'start'=> '10:00AM',
   'end'  => '03:00PM',
),

... эффективно перекрывая все классы, вы получите:

Array
(
    [0] => Array
        (
            [0] => A
            [1] => B
        )

    [1] => Array
        (
            [0] => B
            [1] => D
        )

    [2] => Array
        (
            [0] => C
            [1] => D
        )

    [3] => Array
        (
            [0] => A
            [1] => D
        )

)
0 голосов
/ 17 августа 2011

Отказ от ответственности: Эта функция является более псевдокодом, и вам нужно будет реализовать ее самостоятельно; Возвращает группы перекрывающихся классов. Я написал это так, чтобы вы лучше поняли. Если вам нужно больше объяснений, почему мы должны сначала отсортировать время, дайте мне знать.

function OverLapFunction($time) {
    sort_by_start_time($time); // ensures that we don't have
                               // overlapping groups at the end
    $groups = array(); // groups have starting time, ending
                       // time and items they contain
    foreach($time as $item) {
        // if we don't find a group to put this item in, we create a new one
        $found = false;
        foreach($groups as $group) {
            // basically the whole if statement looks for overlapping between
            // the group and the current item
            if(($item['start_time'] >= $group['start_time'] 
                && $item['start_time'] <= $group['end_time']) ||
                ($item['end_time'] >= $group['start_time']
                &&  $item['end_time'] <= $group['end_time']))
            $group['items'][] = $item; // add the item to its group
            $found = true;
            break;
        }
        if(!$found) { // no group that fits this item; create a new one
            $groups[] = array(
                'start_time' => $item['start_time'], // start and end times
                'end_time' => $item['end_time'],     // are the item's
                'items' => array($item),
            );
        }
    }
    return $groups;
}

Да, и для справки: если у вас есть пользователь, который выбирает некоторые классы, и вам нужно убедиться, что ни один из его выбранных классов не пересекается, вы можете уменьшить проблему до той, которую вы уже поняли:

for($i=0; $i<count($item); $i++) {
    for($j=0; $j<count($item); $j++) {
        if($i == $j) {
            continue;
        }   
        if(times_overlap($item[$i], $item[$j])) {
            do_something(); // the user has chosen incorrect classes
        }
    }
}

Примечание: вышеуказанная проблема может быть улучшена с точки зрения производительности, если вы сортируете элементы по дате начала и просто проверяете, перекрываются ли два последовательных элемента массива.

...