随着时间的推移相关算法的性能 [英] Performance with time related algorithm

查看:169
本文介绍了随着时间的推移相关算法的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,需要2个数组($时间表,$删除),都是用的时间里面天的阵列,它将从计划中删除的时间。

现在此功能工作正常,如果我有1安培之间; 20用户需要2-4秒生成这是很好的日历,但具有很多的时间表20+用户条目时,它会以超过15秒。

我正与codeIgniter和我有一个在那里它被称为很多帮助这个功能。

所以,我想知道,如果你们能看到什么更好的办法来处理我的问题或调整,我做我的算法,使其更快。

注意: 在我下面的code,我看到的最大的问题是递归调用和循环的中断每次我修改的结构。

余两个阵列上环和做测试,以查看是否不存在是内部的可用性/交叠/等于/外面再调出函数,如果将该结构如果没有返回最终结构改性

注意2:

在本地的阿帕奇崩溃,因为递归函数有时被称为100倍以上。

下面是code,我有:

 函数removeSessionsFromSchedule($时间表,$删除){

    $修改= FALSE;
    如果(is_array($时间表)及和放大器;计数($时间表)大于0和放大器;&安培; is_array($删除)及和放大器;计数($删除)> 0安培;&安培; checkArrayEmpty($删除)) {

        //尽量减少迭代
        $删除= minimiseRemoveSchedule($删除);
        的foreach($时间表$ = S> $ DISPO){

            如果($修改){
                打破;
            }

            $ POS = 0;
            $ countdispo =计数($ DISPO);

            的foreach($ DISPO为$ D){

                $ ABS =使用isset($删除[$ S])? $删除[$ S]:空;
                $计数器= 0;
                //可用性的开始/结束
                $ dis_s =的strtotime($ D ['heure_debut']);
                $ dis_e =的strtotime($ D ['heure_fin']);
                如果(is_array($绝对)及&安培;计数($绝对)大于0){
                    的foreach($ ABS和$ a){
                        //没有开始/结束
                        $ abs_s =的strtotime($ A ['heure_debut']);
                        $ abs_e =的strtotime($ A ['heure_fin']);
                        //测试看是否有缺失和可用性之间的重叠
                        //(2)[A_S] --- [DS  - 德] --- [a_e]
                        如果($ abs_s< = $ dis_s和放大器;&安培; $ abs_e> = $ dis_e){
                            //删除可用性
                            取消设置($时间表[$ S] [$ POS]);
                            $修改= TRUE;
                            打破;
                        }
                        //(7)[按==的ds]&安培;&安培; [AE<德]
                        否则,如果($ abs_s == $ dis_s和放大器;&安培; $ abs_e< $ dis_e){
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $时间表[$ S] [$ POS] ['heure_debut'] =日期(H:我,$ abs_e);
                            $时间表[$ S] [$ POS] ['heure_fin'] =日期(H:我,$ dis_e);
                            $修改= TRUE;
                            打破;
                        }
                        //(6)[双链-de] --- [按AE]返回DISPO原样
                        否则,如果($ abs_s> = $ dis_e){
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $修改:假的;
                        }
                        //(5)[作为AE] [双链-de] ---返回DISPO原样
                        否则,如果($ abs_e< = $ dis_s){
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $修改:假的;
                        }
                        //(1)[DS] --- [因为] --- [曝光] --- [德](复制DIS新时代)
                        否则,如果($ abs_s> $ dis_s和放大器;&安培; $ abs_e< = $ dis_e){
                            //新的时代为:// S1 = DS-AS&功放;&安培; S2 = AE-DE
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $时间表[$ S] [$ POS + 1] = $ D;

                            $时间表[$ S] [$ POS] ['heure_debut'] =日期(H:我,$ dis_s);
                            $时间表[$ S] [$ POS] ['heure_fin'] =日期(H:我,$ abs_s);
                            $时间表[$ S] [$ POS + 1] ['heure_debut'] =日期(H:我,$ abs_e);
                            $时间表[$ S] [$ POS + 1] ['heure_fin'] =日期(H:我,$ dis_e);

                            //一个再见硅钙NE引起PAS D'他者的问题qu'on fasse POS ++ ...
                            $ POS ++;

                            $修改= TRUE;
                            打破;
                        }
                        //(3)为]  -  [DS] --- [曝光]  -  [德]
                        否则,如果($ abs_s< $ dis_s和放大器;&安培; $ abs_e< $ dis_e){
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $时间表[$ S] [$ POS] ['heure_debut'] =日期(H:我,$ abs_e);
                            $时间表[$ S] [$ POS] ['heure_fin'] =日期(H:我,$ dis_e);
                            $修改= TRUE;
                            打破;
                        }
                        //(4)[DS] --- [因为] --- [德] --- [曝光]
                        否则,如果($ abs_s> $ dis_s和放大器;&安培; $ abs_s< $ dis_e和放大器;&安培; $ abs_e> $ dis_e){
                            取消设置($时间表[$ S] [$ POS]);
                            $时间表[$ S] [$ POS] = $ D;
                            $时间表[$ S] [$ POS] ['heure_debut'] =日期(H:我,$ dis_s);
                            $时间表[$ S] [$ POS] ['heure_fin'] =日期(H:我,$ abs_s);
                            $修改= TRUE;
                            打破;
                        } 其他 {
                            $修改:假的;
                        }
                    }

                    //如果($修改==真){打破;}


                } 其他 {
                    $修改= FALSE;
                }
                $ POS ++;
            }
        }
    } 其他 {
        $修改= FALSE;
    }

    如果($修改){
        $时间表= resetIndexes($时间表);
        $时间表= sortByTime($时间表);
        $时间表= removeSessionsFromSchedule($时间表,$删除);
    }

    返回$时间表;
}
 

相关助手

 函数checkArrayEmpty($阵列){
    如果(is_array($阵列)及&安培;!空($阵列)){
        的foreach($阵列ARR $){
            如果(is_array($ ARR)及和放大器;!空($ ARR)){
                返回true;
            }
        }
    }
    返回false;
}

功能subval_sort_by_time($ A,$子项){
    如果(is_array($ A)及和放大器;计数($ A)0){
        的foreach($ A $为K => $ V){
            $ B [$ K] =的strtotime($ V [$子键]);
        }
        ASORT($ B);
        的foreach($ B $作为关键=> $ VAL){
            $ C [] = $ A [$关键]
        }
        返回$ C;
    }
    其他
        返回$ A;
}



//重置索引功能
功能resetIndexes($阵列){
        $ =新阵列();
        的foreach($阵列的$ date => $ ARR){
            // $新[$日期] = array_values​​($ ARR);
            $新[$日期= array_merge(数组(),$ ARR);
        }
        返回$新;
    }

//按时间排序
功能sortByTime($阵列){
    $排序=阵列();
    如果(is_array($阵列)及&安培;!空($阵列)){
        的foreach($数组$ = S> $ VAL){
            $排序[$ S] = subval_sort_by_time($ VAL,'heure_debut');
        }
    }
    返回$排序;
  }


 功能minimiseRemoveSchedule($阵列){
    $ =新阵列();
    的foreach($阵列的$ date => $ ARR){
        $ i = 0;
        如果(is_array($ ARR)及和放大器;!空($ ARR)){

            的foreach($ ARR和$ a){

                如果(使用isset($新[$日期] [$ i])){
                    如果($新[$日期] [$ i] ['heure_fin'] = = $ A ['heure_debut']){
                        $新[$日期] [$ i] ['heure_fin'] = $ A ['heure_fin'];
                    }
                    其他 {
                        $ I ++;
                        $新[$日期] [$ i] ['heure_debut'] = $ A ['heure_debut'];
                        $新[$日期] [$ i] ['heure_fin'] = $ A ['heure_fin'];
                    }

                } 其他 {
                    $新[$日期] [$ i] ['heure_debut'] = $ A ['heure_debut'];
                    $新[$日期] [$ i] ['heure_fin'] = $ A ['heure_fin'];
                }
            }
        }
    }
    返回$新;
}
 

数组的例子,我通过:

  $时间表=阵列(
    2012年11月12日'=>阵列()
    二○一二年十一月十三日'=>阵列()
    2012年11月14号'=>阵列(0 =>阵列(employe_id=→8heure_debut=> '16:00',heure_fin=> '20:00',date_seance=> 2012-11- 14,jour_id=→3)),
    2012年11月15号'=>阵列(
        0 =>阵列(employe_id=→8heure_debut=> '09:00',heure_fin=> '15:00',date_seance=> 2012年11月15号,jour_id= →4),
        1 =>阵列(employe_id=→8heure_debut=> '16:00',heure_fin=> '21:00',date_seance=> 2012年11月15号,jour_id= →4)
    ),
    2012年11月16日'=>阵列()
    二零一二年十一月一十七日'=>阵列()
    2012年11月18日'=>阵列()
    2012年11月19日'=>阵列(0 =>阵列(employe_id=→8heure_debut=> '10:00',heure_fin=> '22:00',date_seance=> 2012-11- 19,jour_id=→1)),
    2012年11月20日'=>阵列(
        0 =>阵列(employe_id=→8heure_debut=> '09:00',heure_fin=> '15:00',date_seance=>二〇一二年十一月二十零日,jour_id= →2),
        1 =>阵列(employe_id=→8heure_debut=> '16:00',heure_fin=> '20:00',date_seance=>二零一二年十一月二十日,jour_id= →2)
    )
);
 

和第二阵列:

  $ =删除阵列(
    2012年11月12日'=>阵列()
    二○一二年十一月十三日'=>阵列()
    2012年11月14号'=>阵列()
    2012年11月15号'=>阵列()
    2012年11月16日'=>阵列()
    二零一二年十一月一十七日'=>阵列()
    2012年11月18日'=>阵列()
    //在这个例子中我只有1没有...我可以有N个缺席
    2012年11月19日'=>阵列(0 =>阵列(employe_id=→8date_debut=> 2012年11月19日,date_fin=> 2012年11月19日,heure_debut=> '12:00 :00',heure_fin=> '14:00:00')),
    2012年11月20日'=>阵列()
    2012年11月21号'=>阵列()
);
 

结果数组将是:

  $结果=阵列(
排列
(
       [2012年11月12日] =>阵列()
       [二○一二年十一月十三日] =>阵列()
       // 不用找了
       [2012年11月14号] =>阵列([0] =>阵列(employe_id=> 8,heure_debut=>下午4点,heure_fin=>晚上8点,date_seance=>二○一二年十一月十四日, jour_id=→3))
       // 不用找了
       [2012年11月15号] =>阵列(
                              [0] =>阵列(employe_id=→8heure_debut=> 9时,heure_fin=> 15点00分,date_seance=> 2012年11月15日,jour_id=→4) ,
                              [1] =>阵列(employe_id=> 8,heure_debut=>下午4点,heure_fin=>晚上9点,date_seance=> 2012年11月15日,jour_id=> 4)
                            )
       [2012年11月16日] =>阵列()
       [二○一二年十一月一十七日] =>阵列()
       [2012年11月18日] =>阵列()
       //因为没有从12到14,我们有8到22的可用性,而不是我们将有8> 12和14-> 22
       [2012年11月19日] =>阵列(
                          [0] =>阵列(employe_id=→8heure_debut=>八时,heure_fin=> 12点,date_seance=>二〇一二年十一月二十号,jour_id=→1) ,
                          [1] =>阵列(employe_id=→8heure_debut=> 14:00heure_fin=> 22时,date_seance=>二○一二年十一月二十〇号,jour_id=→1)
                        )
       //在这些时候,因为没有没有没有改变
       [2012年11月20日] =>阵列(
                          [0] =>阵列(employe_id=→8heure_debut=> 9时,heure_fin=> 15点00分,date_seance=>二○一二年十一月二十○号,jour_id=→2) ,
                          [1] =>阵列(employe_id=> 8,heure_debut=> 16:00,heure_fin=> 20:00,date_seance=>二○一二年十一月二十〇号,jour_id=> 2)
                        )
)
 

解决方案

在code以下产生相同的输出对于给定的样本,但我没有测试所有可能的情况。

工作演示

 函数removeSessionsFromScheduleHelper(安培; $时间表,和放大器; $删除){

    $变化= FALSE;

    的foreach($除去为$日期=>&安培; $ remove_ranges){

        如果(空($ remove_ranges)||!使用isset($时间表[$日期))
            继续;

        的foreach($ remove_ranges为&放大器; $ remove_range){
            的foreach($时间表[$日期]为$ day_key =>&安培; $时间){

                说完,没有重叠后//开始因为日程安排进行排序
                在调度循环//下一个项目也不会重叠
                //打破计划环路放大器;移动到下一个删除迭代
                如果($时间['heure_debut']≥= $ remove_range ['heure_fin'])
                    打破;

                //结束开始前,没有重叠
                如果($时间['heure_fin']< = $ remove_range ['heure_debut'])
                    继续;

                //完全重叠,删除
                如果($时间['heure_debut']≥= $ remove_range ['heure_debut']
                  &功放;&安培; $时间['heure_fin']< = $ remove_range ['heure_fin']){
                    取消设置($时间表[$日期] [$ day_key]);
                    继续;
                }

                //分成2个范围
                如果($时间['heure_debut']< $ remove_range ['heure_debut']){

                    如果($时间['heure_fin']≥$ remove_range ['heure_fin']){
                        $时间表[$日期] [] =阵列(
                            heure_debut'=> $ remove_range ['heure_fin'],
                            heure_fin'=> $时间['heure_fin']
                        );
                    }

                    $变化= TRUE;
                    $时间['heure_fin'] = $ remove_range ['heure_debut'];
                    继续;
                }

                如果($时间['heure_debut']≥= $ remove_range ['heure_debut']){
                    $变化= TRUE;
                    $时间['heure_debut'] = $ remove_range ['heure_fin'];
                }
            }
        }
    }

    如果($其他城市){
       的foreach($时间表和放大器; $值){
          usort($值,'compare_schedule');
       }
    }

    返回$变化;
}

功能compare_schedule($ A,$ B){
    返回的strtotime($ A ['heure_debut']) - 的strtotime($ B ['heure_debut']);
}

功能removeFromSchedule(安培; $时间表,$删除){

    的foreach($除去为$ K =>&安培; $ V){
        的foreach($ V为$ K2 =>&安培; $ V2){
            $ V2 ['heure_debut'] = SUBSTR($ V2 ['heure_debut'],0,5);
            $ V2 ['heure_fin'] = SUBSTR($ V2 ['heure_fin'],0,5);
        }
    }

    而(removeSessionsFromScheduleHelper($时间表,$删除));
}

removeFromSchedule($时间表,$删除);
的print_r($时间表);
 

I have a function that take 2 arrays ($schedule, $remove), both are arrays of days with time inside, it will remove time from the schedule .

Now this function is working fine if I have between 1 & 20 user it takes 2-4 seconds to generate the calendar which is fine but when having 20+ user with a lot of schedules entries it goes to 15+ seconds.

I'm working with CodeIgniter and I have this function in a helper where it's called a lot.

So I wanted to know if you guys can see any better way to deal with my problem or adjustments that I make to my algorithm to make it faster.

Note: In my code below, the big problem I see is the recursive call and the break of the loop every time I modify the structure.

I loop on both arrays and do test to see if the absence is inside/overlap/equal/outside of the availability and then recall the function if the structure was modified if not return the final structure.

Note 2 :

On local the Apache crash because the recursive function sometime is called more than 100 times .

Here is the code I have :

   function removeSessionsFromSchedule($schedule, $remove) {

    $modified = false;
    if (is_array($schedule) && count($schedule) > 0 && is_array($remove) && count($remove) > 0 && checkArrayEmpty($remove)) {

        // Minimise the iterations
        $remove = minimiseRemoveSchedule($remove);
        foreach ($schedule as $s => $dispo) {

            if ($modified) {
                break;
            }

            $pos        = 0;
            $countdispo = count($dispo);

            foreach ($dispo as $d) {

                $abs = isset($remove[$s]) ?  $remove[$s] :null;
                $counter = 0;
                // availability start/end
                $dis_s = strtotime($d['heure_debut']);
                $dis_e = strtotime($d['heure_fin']);
                if (is_array($abs) && count($abs) > 0) {
                    foreach ($abs as $a) {
                        // absence start/end
                        $abs_s = strtotime($a['heure_debut']);
                        $abs_e = strtotime($a['heure_fin']);
                        // Tests to see the if there is overlap between absence and availability
                        // (2) [a_s]---[ds - de]---[a_e]
                        if ($abs_s <= $dis_s && $abs_e >= $dis_e) {
                            // delete availability
                            unset($schedule[$s][$pos]);
                            $modified = true;
                            break;
                        }
                        // (7)[as == ds] && [ae < de]
                        else if ($abs_s == $dis_s && $abs_e < $dis_e) {
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $schedule[$s][$pos]['heure_debut'] = date("H:i", $abs_e);
                            $schedule[$s][$pos]['heure_fin'] = date("H:i", $dis_e);
                            $modified = true;
                            break;
                        }
                        // (6) [ds -de] --- [as  ae] return dispo as is
                        else if ($abs_s >= $dis_e) {
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $modified ?: false;
                        }
                        // (5)[as  ae] [ds -de] ---  return dispo as is
                        else if ($abs_e <= $dis_s) {
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $modified ?: false;
                        }
                        // (1)[ds] --- [as] --- [ae] --- [de] (duplicate dis with new times)
                        else if ($abs_s > $dis_s && $abs_e <= $dis_e) {
                            // new times as : // s1 = ds-as &&  s2 = ae-de
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $schedule[$s][$pos + 1] = $d;

                            $schedule[$s][$pos]['heure_debut'] = date("H:i", $dis_s);
                            $schedule[$s][$pos]['heure_fin'] = date("H:i", $abs_s);
                            $schedule[$s][$pos + 1]['heure_debut'] = date("H:i", $abs_e);
                            $schedule[$s][$pos + 1]['heure_fin'] = date("H:i", $dis_e);

                            // a revoir si ca ne cause pas d'autre problem qu'on fasse pos++ ...
                            $pos++;

                            $modified = true;
                            break;
                        }
                        // (3)[as] -- [ds] --- [ae] -- [de]
                        else if ($abs_s < $dis_s && $abs_e < $dis_e) {
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $schedule[$s][$pos]['heure_debut'] = date("H:i", $abs_e);
                            $schedule[$s][$pos]['heure_fin'] = date("H:i", $dis_e);
                            $modified = true;
                            break;
                        }
                        // (4) [ds]---[as]--- [de]--- [ae]
                        else if ($abs_s > $dis_s && $abs_s < $dis_e && $abs_e > $dis_e) {
                            unset($schedule[$s][$pos]);
                            $schedule[$s][$pos] = $d;
                            $schedule[$s][$pos]['heure_debut'] = date("H:i", $dis_s);
                            $schedule[$s][$pos]['heure_fin'] = date("H:i", $abs_s);
                            $modified = true;
                            break;
                        } else {
                            $modified ?: false;
                        }
                    }

                    // if($modified == true) { break;}


                } else {
                    $modified = false;
                }
                $pos++;
            }
        }
    } else {
        $modified = false;
    }

    if ($modified) {
        $schedule = resetIndexes($schedule);
        $schedule = sortByTime($schedule);
        $schedule = removeSessionsFromSchedule($schedule, $remove);
    }

    return $schedule;
}

Related Helpers

function checkArrayEmpty($array) {
    if(is_array($array) && !empty($array)) {
        foreach($array as $arr) {
            if(is_array($arr) && !empty($arr)) {
                return true;
            }
        }
    }
    return false;
}

function subval_sort_by_time($a, $subkey) {
    if (is_array($a) && count($a) > 0) {
        foreach ($a as $k => $v) {
            $b[$k] = strtotime($v[$subkey]);
        }
        asort($b);
        foreach ($b as $key => $val) {
            $c[] = $a[$key];
        }
        return $c;
    }
    else
        return $a;
}



// Reset Index function 
function resetIndexes($array) {
        $new = array();
        foreach($array as $date => $arr) {
            //$new[$date]= array_values($arr);
            $new[$date]= array_merge(array(),$arr);
        }
        return $new;
    }

// sort by time
function sortByTime($array) {
    $sorted = array();
    if(is_array($array) && !empty($array)){
        foreach ($array as $s => $val) {
            $sorted[$s] = subval_sort_by_time($val, 'heure_debut');
        }
    }
    return $sorted;
  }


 function minimiseRemoveSchedule($array) {
    $new = array();
    foreach($array as $date => $arr) {
        $i=0;
        if(is_array($arr) && !empty($arr)) {

            foreach($arr as $a) {

                if(isset($new[$date][$i])) {
                    if($new[$date][$i]['heure_fin'] == $a['heure_debut']) {
                        $new[$date][$i]['heure_fin']  = $a['heure_fin'];
                    }
                    else {
                        $i++;
                        $new[$date][$i]['heure_debut'] = $a['heure_debut'];
                        $new[$date][$i]['heure_fin']   = $a['heure_fin'];
                    }

                } else {
                    $new[$date][$i]['heure_debut'] = $a['heure_debut'];
                    $new[$date][$i]['heure_fin']   = $a['heure_fin'];
                }
            }
        }
    }
    return $new;
}

Example of Array that I pass:

$schedule = Array(
    '2012-11-12' => Array(),
    '2012-11-13' => Array(),
    '2012-11-14' => Array( 0 => Array("employe_id" => 8 , "heure_debut" => '16:00' ,"heure_fin" => '20:00' ,"date_seance" => 2012-11-14 , "jour_id" => 3)),
    '2012-11-15' => Array( 
        0 => Array("employe_id" => 8 , "heure_debut" => '09:00' ,"heure_fin" => '15:00' ,"date_seance" => 2012-11-15 , "jour_id" => 4),
        1 => Array("employe_id" => 8 , "heure_debut" => '16:00' ,"heure_fin" => '21:00' ,"date_seance" => 2012-11-15 , "jour_id" => 4)
    ),
    '2012-11-16' => Array(),
    '2012-11-17' => Array(),
    '2012-11-18' => Array(),
    '2012-11-19' => Array(0 => Array("employe_id" => 8 ,"heure_debut" => '10:00' ,"heure_fin" => '22:00' ,"date_seance" => 2012-11-19 ,"jour_id" => 1)),
    '2012-11-20' => Array(
        0 => Array("employe_id" => 8 ,"heure_debut" => '09:00' ,"heure_fin" => '15:00' ,"date_seance" => 2012-11-20 ,"jour_id" => 2),
        1 => Array("employe_id" => 8 ,"heure_debut" => '16:00' ,"heure_fin" => '20:00' ,"date_seance" => 2012-11-20 ,"jour_id" => 2)
    )
);

And for the second array:

$remove = array(
    '2012-11-12' => Array(),
    '2012-11-13' => Array(),
    '2012-11-14' => Array(),
    '2012-11-15'  => Array(),
    '2012-11-16' => Array(),
    '2012-11-17' => Array(),
    '2012-11-18' => Array(),
    // in this example i only have 1 absence ... I could have N absences
    '2012-11-19' => Array(0 => Array("employe_id" => 8 ,"date_debut" => 2012-11-19,"date_fin" => 2012-11-19  ,"heure_debut" => '12:00:00',"heure_fin"   => '14:00:00')),
    '2012-11-20' => Array(),
    '2012-11-21' => Array()
);

The resulting array would be:

$result = array(
Array
(
       [2012-11-12] => Array()
       [2012-11-13] => Array()
       // no change 
       [2012-11-14] => Array( [0] => Array("employe_id" => 8 , "heure_debut" => 16:00 ,"heure_fin" => 20:00 ,"date_seance" => 2012-11-14 , "jour_id" => 3))
       // no change
       [2012-11-15] => Array( 
                              [0] => Array("employe_id" => 8 , "heure_debut" => 09:00 ,"heure_fin" => 15:00 ,"date_seance" => 2012-11-15 , "jour_id" => 4),
                              [1] => Array("employe_id" => 8 , "heure_debut" => 16:00 ,"heure_fin" => 21:00 ,"date_seance" => 2012-11-15 , "jour_id" => 4)
                            )
       [2012-11-16] => Array()
       [2012-11-17] => Array()
       [2012-11-18] => Array()
       // since absence from 12 to 14 and  we had availability from 8 to 22 instead we will have 8->12 and 14->22
       [2012-11-19] => Array(
                          [0] => Array("employe_id" => 8 ,"heure_debut" => 08:00 ,"heure_fin" => 12:00 ,"date_seance" => 2012-11-20 ,"jour_id" => 1),
                          [1] => Array("employe_id" => 8 ,"heure_debut" => 14:00 ,"heure_fin" => 22:00 ,"date_seance" => 2012-11-20 ,"jour_id" => 1)
                        )
       // no changes since no absence during those time
       [2012-11-20] => Array(
                          [0] => Array("employe_id" => 8 ,"heure_debut" => 09:00 ,"heure_fin" => 15:00 ,"date_seance" => 2012-11-20 ,"jour_id" => 2),
                          [1] => Array("employe_id" => 8 ,"heure_debut" => 16:00 ,"heure_fin" => 20:00 ,"date_seance" => 2012-11-20 ,"jour_id" => 2)
                        )
)

解决方案

The code below produces the same output for the given sample but I haven't tested all possible cases.

Working Demo

function removeSessionsFromScheduleHelper(&$schedule,&$remove) {

    $change = false;

    foreach($remove as $date => &$remove_ranges) {

        if(empty($remove_ranges) || !isset($schedule[$date]))
            continue;

        foreach($remove_ranges as &$remove_range) {
            foreach($schedule[$date] as $day_key => &$time) {

                //start after finish, no overlap and because schedules are sorted
                //next items in schedule loop will also not overlap
                //break schedule loop & move to next remove iteration
                if($time['heure_debut'] >= $remove_range['heure_fin'])
                    break;

                //finish before start, no overlap
                if($time['heure_fin'] <= $remove_range['heure_debut'])
                    continue;

                //complete overlap, remove
                if($time['heure_debut'] >= $remove_range['heure_debut']
                  && $time['heure_fin'] <= $remove_range['heure_fin']) {
                    unset($schedule[$date][$day_key]);
                    continue;
                }

                //split into 2 ranges
                if($time['heure_debut'] < $remove_range['heure_debut']) {

                    if($time['heure_fin'] > $remove_range['heure_fin']) {
                        $schedule[$date][] = array(
                            'heure_debut' => $remove_range['heure_fin'],
                            'heure_fin' => $time['heure_fin']
                        );
                    }

                    $change = true;
                    $time['heure_fin'] = $remove_range['heure_debut'];                     
                    continue;
                }

                if($time['heure_debut'] >= $remove_range['heure_debut']) {
                    $change = true;
                    $time['heure_debut'] = $remove_range['heure_fin'];
                }                
            }
        }
    }

    if($change) {    
       foreach($schedule as &$values) {
          usort($values,'compare_schedule');
       }
    }

    return $change;
}

function compare_schedule($a,$b) {
    return strtotime($a['heure_debut']) - strtotime($b['heure_debut']);
}

function removeFromSchedule(&$schedule,$remove) {

    foreach($remove as $k => &$v) {
        foreach($v as $k2 => &$v2) {
            $v2['heure_debut'] = substr($v2['heure_debut'],0,5);
            $v2['heure_fin'] = substr($v2['heure_fin'],0,5);
        }
    }

    while(removeSessionsFromScheduleHelper($schedule,$remove));    
}

removeFromSchedule($schedule,$remove);
print_r($schedule);

这篇关于随着时间的推移相关算法的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆