前提:我正在一个需要PHP 5.2兼容的项目中工作,很遗憾,我不能使用PHP 5.3+ DateInterval
或其他PHP>=5.3仅限的指令。
我有一个包含以$k => $v
范围表示的营业时间的数组,因此键是开始,值是结束,如下所示:
array(
09:00 => 11:30
09:30 => 11:00
10:00 => 12:30
13:30 => 14:30
)
在这个例子中,我们有前三对重叠的范围,我可以将其表示为09:00 => 12:30
(意思是:在上午9点开放,在下午12点30分关闭),因为前三对的开始和结束是重叠的。
我也可以这样写数组,作为整数(或者我可以使用浮点数,例如09:30
变成9.3
,我认为没关系):
array(
900 => 1130
930 => 1100
1000 => 1230
1330 => 1430
)
如何将数组转换为:
array(
900 => 1230
1330 => 1430
)
我想到的想法是循环数组,使用array_slice
,通过引用传递值和unset()
的东西,而在它…但我不确定这是不是最好的主意,或者我只是把它复杂化了。
这个问题有很多解决方案;我:
http://phpfiddle.org/main/code/batv-hzqw希望它足够清楚,并满足您所制定的标准——如果不是,请告诉我:)
进行这种类型的重叠检查的一种方法是使用以下算法:测试两个整数范围重叠的最有效方法是什么?
伪代码循环你所有的时间范围,如果它们重叠,把它们放在同一个桶里。
:
<?php
$times = array(
900 => 1130,
930 => 1100,
1000 => 1230,
1330 => 1430,
845 => 900,
1330 => 1700,
845 => 1000
);
function reduceOverlap($times) {
$reduced = array();
//Put the first entry into our final bucket
$reduced[array_keys($times)[0]] = $times[array_keys($times)[0]];
foreach ($times as $start => $end) {
// Trip this flag if a new bucket does not need to be created
$foundOverlap = false;
// Check if this time can go in one of our buckets
foreach ($reduced as $reducedStart => $reducedEnd) {
// Truthy check for overlap of time range with bucket range
if ($start <= $reducedEnd && $end >= $reducedStart) {
// Use this for start key incase it gets changed
$startKey = $reducedStart;
// Was the start less than the bucket's start?
// If yes update bucket's start time
if ($start < $reducedStart) {
unset($reduced[$reducedStart]);
$reduced[$start] = $reducedEnd;
$startKey = $start;
}
// Was the end greater than the bucket's end?
// If yes update bucket's end time
if ($end > $reducedEnd) {
$reduced[$startKey] = $end;
}
$foundOverlap = true;
}
}
// There was no overlap, create a new bucket
if (!$foundOverlap) {
$reduced[$start] = $end;
}
}
return $reduced;
}
var_dump(reduceOverlap($times));
输出:array(2) {
[1330]=>
int(1700)
[845]=>
int(1230)
}