随时间变化的算法对性能的影响

13

我有一个函数,它接受两个数组($schedule, $remove),这两个数组都是带有时间的日期数组,它将从计划中删除时间。

现在,如果我有1到20个用户,这个函数的工作正常,生成日历需要2-4秒,这很好,但是当有20多个用户并且有大量计划条目时,需要15秒以上。

我使用CodeIgniter,在helper中拥有这个函数,在很多地方都会调用它。

所以我想知道你们是否能看到更好的方法来处理我的问题或者调整我的算法使其更快。

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

我循环遍历两个数组,并进行测试,以查看缺席是否在可用性内/重叠/相等/外部,然后如果结构已修改,则重新调用函数,否则返回最终结构。

注2 :

在本地,Apache会崩溃,因为递归函数有时被调用超过100次。

这里是我的代码:

   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;
}

相关辅助函数

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;
}

我传递的数组示例:

$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)
    )
);

对于第二个数组:

$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()
);

生成的数组将会是:

$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)
                        )
)

1
我看到你的代码中有太多重复,而且我不认为需要使用递归。请提供一个简单的函数规范,说明你的函数应该做什么。 - Baba
我看到你的每个条目中都有一个“employe_id”字段。在你的代码示例中似乎没有检查该字段,但它确实很重要,不是吗? - didierc
1
http://php.net/break - 这个可以有一个“参数”。您还可能希望利用http://php.net/goto来更好地表达您在代码中所做的事情,而不需要递归 - 特别是因为您更喜欢过程化方法。 - hakre
@didierc 在这个特定的函数中并不重要,但由于此函数返回所有用户的时间表...我使用它来显示每个教师最终的可用性。 - Tarek
6个回答

5

我不明白为什么需要指数时间的递归来执行这个任务。你可以通过嵌套循环得到一个 O(r * e^2) 的解决方案(其中e是每天可用性/删除次数的平均数,r是被删除时间的大小)。以下是假代码:

for removeday in remove:
    define scheduleday := schedule[removeday.date]
    if scheduleday not found:
        continue
    for removesegment in removeday:
        define temparray := empty
        for availsegment in scheduleday:
            if availsegment.employeid != removesegment.employeid:
                continue
            if no overlap:
                temparray.add(availsegment)
            if partial overlap:
                temparray.add(availsegment.split(removesegment))
        scheduleday = temparray
    schedule[removeday.date] := scheduleday
return schedule

我添加了递归,因为你需要重新检查临时时间。你添加了两个数组(scheduled 和 remove)可能包含多个条目,具有不同的时间,以便能够正确处理。 - Tarek
3
在这种情况下,按照起始时间递增的顺序对“temparray”进行排序。从左到右扫描数组,跟踪每个雇员遇到的最大结束时间。如果开始时间恰好小于最大结束时间,则将该时间段的开始时间设置为最大结束时间(如果开始时间最终大于结束时间,则完全删除该时间段)。 - jma127

2

如果您不想在函数中添加递归,那么您需要将其转换为可用时间表数组矩阵的秒数。以下是思路:

function scheduleToSecondsMatrix($value, $available=true){

    if(!is_array($value) || empty($value))
        return false;

    $object = array();

    foreach($value as $v) {
        $s = strtotime('1970-01-01 ' . $v['heure_debut'] . (!$available ? ' +1 seconds' : '')); // ref. https://dev59.com/WW445IYBdhLWcg3w_O8m
        $e = strtotime('1970-01-01 ' . $v['heure_fin'] . (!$available ? ' -1 seconds' : ''));

        if($e < $s) continue; // logically end time should be greater than start time

        while($s <= $e) {
            // i use string as key as this result will be merged: http://php.net/manual/en/function.array-merge.php
            $object["in_" . $s] = $available; // means in this seconds range is available
            $s++;
        }
    }

    return $object;
}

/**
 * This function assume: 
 * - all parameters refer to only one employee
 */
function removeSessionsFromScheduleRev($schedule, $remove) {

    if(!is_array($schedule) || !is_array($remove) || empty($schedule) || empty($remove)) return false;

    foreach($schedule as $s => &$dispo){

        if(empty($remove[$s]))
            continue;

        // convert the schedule to seconds array matrix, that's i call it :)
        $seconds_available = scheduleToSecondsMatrix($dispo, true);
        $seconds_not_available = scheduleToSecondsMatrix($remove[$s], false);

        if( !$seconds_available || !$seconds_not_available ) continue; // nothing changed

        $seconds_new = array_merge($seconds_available, $seconds_not_available);
        $seconds_new = array_filter($seconds_new); // remove empty/false value

        $new_time_schedule = array();
        $last_seconds = 0;

        $i=0;

        foreach($seconds_new as $in_seconds => $val){

            $in_seconds = intval(str_replace('in_', '', $in_seconds));

            if($in_seconds > ($last_seconds+1)){
                if(!empty($new_time_schedule)) $i++;
            }

            if(empty($new_time_schedule[$i]['start'])) $new_time_schedule[$i]['start'] = $in_seconds;
            $new_time_schedule[$i]['end'] = $in_seconds;

            $last_seconds = $in_seconds;
        }

        foreach($new_time_schedule as $idx => $val){
            if($idx && empty($dispo[$idx])) $dispo[$idx] = $dispo[$idx-1];

            $dispo[$idx]['heure_debut'] = date('H:i:s', $val['start']);
            $dispo[$idx]['heure_fin'] = date('H:i:s', $val['end']);
        }
    }

    return $schedule;
}

我还没有对性能进行基准测试,所以你可以在自己的设备上尝试这段代码。希望它能正常工作。


我的函数执行时间为0.036秒,而你的函数执行时间为1.377秒,并且返回了错误的数据。 - Tarek

2
以下代码对于给定的示例生成相同的输出,但我尚未测试所有可能的情况。 演示链接
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);

1
谢谢,比我看到的更快,而且返回正确的结果(0.07 vs 你的:0.005)。 - Tarek
我所做的唯一修改就是在 while 循环后返回结构。 - Tarek
2
@Tarek removeFromSchedule 接收 $schedule 作为引用(请注意参数中的 &),因此它修改了原始参数,无需从函数中返回。我这样做是因为通过引用传递比返回(和复制)数组更快。 - FuzzyTree
我不得不退回它,因为它在其他函数内部,并且这些函数期望某些东西,为了避免修改站点中的所有代码,在长期内我最终将不得不修改它。 - Tarek
你看到有什么问题吗? - Tarek
@Tarek 没问题,除非你的数组非常大,否则这可能不会有什么影响,即使如此,引用对于辅助函数更重要,因为它在 while 循环中被调用。 - FuzzyTree

1

我认为jma127的伪代码是正确的。让我补充一些评论。

您的基本结构是循环遍历$schedule的条目,然后对于每个条目,从$remove中提取相应的条目,并进行一些更改。一旦发生更改,您就会跳出循环,并重新开始。您用于重新开始的控制结构是递归调用。当您重新开始时,再次循环遍历所有已经检查过且不需要再更改的$schedule条目。

数组$ schedule和数组$ remove通过共享下标相关联。对于给定的索引$i$,$remove[i]$仅影响$schedule[i]$而不影响其他部分。如果没有条目$remove[i]$,则$schedule[i]$保持不变。因此,jma127正确地重构了循环,首先迭代$remove$的条目,并具有内部代码块来组合$remove[i]$和$schedule[i]$的条目。无需递归,也无需重复迭代$schedule$。
我相信这是您的代码在条目数量增加时变慢的主要原因。
对于$remove$和$schedule$中某一天的条目,您将它们组合的方式基于开始时间和结束时间。 jma127指出,如果按时间排序(首先为开始时间,其次为结束时间),则可以通过两个数组进行单次遍历,并得到正确的结果。无需递归或重复循环。

我相信这是你的代码变慢的次要原因。

我注意到你的代码还有一件事情,就是你经常把不受循环影响的代码放在循环内部。把它放在循环外面会更有效率一点。例如,你对$remove$schedule进行的有效性检查:

if (is_array($schedule) && count($schedule) > 0 \
  && is_array($remove) && count($remove) > 0)...

每次递归调用例程时都会重复执行此操作。您可以将此检查移动到外部函数中,该函数调用内部函数,而内部函数则不需要再次检查$remove$schedule

function removeSessionsFromSchedule_outer($schedule, $remove) {

    if (   is_array($schedule) && count($schedule) > 0 
        && is_array($remove) && count($remove) > 0     ) {
        $schedule = removeSessionsFromSchedule($schedule, $remove);
    }

    return $schedule;
}

同样地,

foreach ($dispo as $d) {
    if (isset($remove[$s])) {
        $abs = $remove[$s];
    } else
        $abs = null;
    // rest of loop....
}/*foreach*/

可以重写为:

if (isset($remove[$s])) {
    $abs = $remove[$s];
} else
     $abs = null;
foreach ($dispo as $d) {
    // rest of loop....
}/*foreach*/

另一个小的低效率是你的数据结构不包含你需要的格式的数据。你没有收到一个包含如下数据的结构:
[2012-11-14] => Array( [0] => Array(..."heure_debut" => 16:00 ...))

每次循环期间,执行数据转换操作,例如:

$abs_s = strtotime($a['heure_debut']);

你觉得让上游的调用方自己转换数据怎么样?

["2012-11-14"] => Array([0]=>Array(..."heure_debut"=>strtotime("16:00") ...))

另一个小细节是您使用类似于2012-11-1416:00的语法。PHP将其视为字符串,但如果将它们放在引号中以明确它们是字符串,您的代码会更清晰。请参见{{link1:为什么$foo [bar]在PHP文档数组中是错误的?}}。

我不会尝试重写您的代码以进行所有这些更改。我猜您可以自己看看我的评论和jma127的答案来解决问题。


1

您有一个可用性日程表,以日期和条目编号为基础实现为二维数组,还有一个缺席日程表,同样以相同方式实现,两者都按时间排序,并希望首先使用第二个更新第一个。

这两个数组在其主要维度上(使用日期)进行索引,因此我们可以安全地处理每行而不担心修改其他数组。

对于给定的一天:

在一天内,最简单的方法是循环遍历所有$remove 条目,并针对每个匹配的员工ID检查时间并相应地修改日程表(您已经实现了某些内容,因此我们可以重复使用它)。您希望按时间顺序保留当天的日程表。原始数组已经排序良好,如果我们将修改存储在新数组中以创建顺序,则之后就不必对其进行排序。

<?php

// create a schedule entry from template, with begin & end time
function schedule($tmpl, $beg, $end) {
    $schedule = $tmpl;
    $schedule['heure_debut'] = date("H:i", $beg);
    $schedule['heure_fin'] = date("H:i", $end);
    return $schedule;
}

// return one updated entry of a schedule day, based on an absence
function updateAvailability($d, $a){
    // absence start/end
    $dis_s = strtotime($d['heure_debut']);
    $dis_e = strtotime($d['heure_fin']);
    $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) {
        return array();
    }
    // (7)[as == ds] && [ae < de]
    else if ($abs_s == $dis_s && $abs_e < $dis_e) {
        return array(schedule($d,$abs_e,$dis_e));
    }
    // (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
        return array(schedule($d,$dis_s,$abs_s), schedule($d,$abs_e,$dis_e));
    }
    // (3)[as] -- [ds] --- [ae] -- [de]
    else if ($abs_s < $dis_s && $abs_e < $dis_e) {
        return array(schedule($d,$abs_e,$dis_e));
    }
    // (4) [ds]---[as]--- [de]--- [ae]
    else if ($abs_s > $dis_s && $abs_s < $dis_e && $abs_e > $dis_e) {
        return array(schedule($d,$dis_s,$abs_s));
    }
    return array($d);
}

// move through all the entries of one day of schedule, and change
function updateDaySchedule($day, $absence){
    $n = array();
    foreach($day as $avail){
        // intersect availability with absence
        $a = updateAvailability($avail,$absence);
        // append new entries
        $n = array_merge($n, $a);
    }
    return $n;
}    

function removeSessionsFromSchedule($schedule, $remove) {
    if (!checkValidScheduleInput($schedule,$remove) 
        return $schedule;
    foreach($remove as $day => $absences) {
        // only update matching schedule day
        if (isset($schedule[$day])) {
            foreach ($absences as $abs)
                $schedule[$day] = updateDaySchedule($schedule[$day], $abs);
        }
    }
    return $schedule;
}

?>

还有一些改进的空间:

  • updateAvailability 函数中的 $dis_s$dis_e 等值每次都会重新计算,而有些值可以只计算一次并作为参数传递给函数。不过这可能并不值得麻烦。

  • 'heure_debut' 等常量可以定义为已定义的常量:

    define('HD','heure_debut');

    这样可以避免可能的拼写错误(PHP 会告诉你常量是否拼写错误,但对于字符串字面量则不会),并且如果键名需要更改,则更容易进行重构。


“check”函数是用来做什么的? - Tarek
说实话,我不知道,已经很久了。这个注释的意思是:// 在这里放置对employee_id匹配等进行测试。我猜当记录被比较时,您可能想要进行此类验证。 - didierc
我认为这个想法是有两种过滤类别:一种是时间匹配,另一种是其他属性(如员工ID匹配)。我认为将它们分开是一个好主意,这样你就可以添加任何进一步的过滤,而不必编辑整个代码。 - didierc
目前没有对其他匹配项进行过滤,因此仅限于时间。 - Tarek
我认为我已经修复了代码中的一些问题(显然在发布答案时我没有检查)。抱歉!如果还有其他问题,请告诉我。 - didierc
显示剩余2条评论

0
函数的递归性质是你的问题,函数中除此之外没有太多的处理能力,所以这应该很快。你真的需要找到一种不用递归来进行处理的方法。

这就是我所要求的 :) - Tarek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接