基于重叠实体数组创建新数组

时间:2011-01-07 12:59:48

标签: php arrays algorithm performance

你有没有一天你的大脑没有脱离一档?

我有一个包含开始和结束时间的数组。我想创建一个新数组,显示初始数组中重叠条目的键。所以,说我们有一些“保留”。任何重叠的“预订”都属于同一个“会话”。一个初始数组,如:

[reservations] => Array
    (
        [1125] => Array
            (
                [start] => 2011-01-07 10:00:00
                [end] => 2011-01-07 10:30:00
            )
        [1244] => Array
            (
                [start] => 2011-01-07 10:15:00
                [end] => 2011-01-07 11:30:00
             )
        [1311] => Array
            (
                [start] => 2011-01-07 11:00:00
                [end] => 2011-01-07 11:45:00
            )
        [1422] => Array
            (
                [start] => 2011-01-07 12:00:00
                [end] => 2011-01-07 12:30:00
             )
        [1561] => Array
            (
               [start] => 2011-01-07 12:30:00
               [end] => 2011-01-07 12:45:00
            )
        [1622] => Array
            (
               [start] => 2011-01-07 13:00:00
               [end] => 2011-01-07 13:45:00
            )
    )

将生成一个新的数组,如:

[sessions] => Array
    (
        [0] => Array
            (
                [0] => 1125
                [1] => 1244
                [2] => 1311
            )
        [1] => Array
            (
                [0] => 1422
                [1] => 1561
            )
        [2] => Array
            (
                [0] => 1622
            )
    )

对大型阵列执行此操作的最有效方法是什么?谢谢!

2 个答案:

答案 0 :(得分:3)

对于每个预留,将其(start,id)和(end,id)(单独)放入在第一个项目(即时间)上排序的元组数组中。然后从最低时间到最高时间遍历数组,保留保留是开放的,将每个新的保留在同一个会话中。关闭会话中的最后一个预留后,关闭会话。

答案 1 :(得分:0)

不是真正的代码,因此没有经过测试,但可能是一种方式:

foreach([reservations] as $key => $res){
    $a[ timestamp_of( $res[start] ) ] = $key;
    $a[ timestamp_of( $res[end] ) ] = $key;
}

ksort($a, SORT_NUMERIC);  //sort by timestamp

$open = Array();   //currently 'open' reservations while looping through
$sesions = Array();    //result array for sessions
$active = 0;    //ID of active session

foreach($a as $item){
    if($item in $open) {    //check if current reservation is in list of open ones

        strip($item, $open);    //if so: close it → remove from array
        if( sizeof( $open ) == 0 ) $active++;   //if no reservations open, close the session

    } else {     //if current reservation is not open...

        $open[$item] = true;    //open it
        $sessions[$active][] = $item    //and add it to current session

    }
}