Мой метод создаст объединенный массив, в котором перекрывающиеся или последовательные даты группируются вместе, а идентификаторы группы сохраняются в виде строки значений, разделенных запятой.
Я использую современный «оператор космического корабля» (<=>
) для сравнения usort()
s. Если ваш код работает на версии ниже php7, вы можете использовать:
usort($array,function($a,$b){ return strcmp($a['start_date'],$b['start_date']); });
См. Встроенные комментарии для пошагового объяснения.
Код: ( Демо )
function mergeRanges($array){
usort($array,function($a,$b){ return $a['start_date']<=>$b['start_date']; }); // order by start_date ASC
foreach($array as $i=>$row){
if($i && $row['start_date']<=date('Y-m-d',strtotime("{$result[$x]['end_date']} +1 day"))){ // not the first iteration and dates are within current group's range
if($row['end_date']>$result[$x]['end_date']){ // only if current end_date is greater than existing end_date
$result[$x]['end_date']=$row['end_date']; // overwrite end_date with new end_date in group
}
$result[$x]['merged_ids'][]=$row['id']; // append id to merged_ids subarray
}else{ // first iteration or out of range; start new group
if($i){ // if not first iteration
$result[$x]['merged_ids']=implode(', ',$result[$x]['merged_ids']); // convert previous group's id elements to csv string
}else{ // first iteration
$x=-1; // declare $x as -1 so that it becomes 0 when incremented with ++$x
}
$result[++$x]=['merged_ids'=>[$row['id']],'start_date'=>$row['start_date'],'end_date'=>$row['end_date']]; // declare new group
}
}
$result[$x]['merged_ids']=implode(', ',$result[$x]['merged_ids']); // convert final merged_ids subarray to csv string
return $result;
}
$array=[
['id'=>18298,'start_date'=>'2011-07-09','end_date'=>'2011-10-01'],
['id'=>18297,'start_date'=>'2011-06-01','end_date'=>'2011-06-30'],
['id'=>17113,'start_date'=>'2011-03-31','end_date'=>'2011-05-31'], // tests that 17113 and 18297 belong in same group
['id'=>20556,'start_date'=>'2011-02-03','end_date'=>'2011-02-13'], // tests that "fully overlapped" date range is included
['id'=>20555,'start_date'=>'2011-01-03','end_date'=>'2011-03-31']
];
print_r(mergeRanges($array));
Выход:
Array
(
[0] => Array
(
[merged_ids] => 20555, 20556, 17113, 18297
[start_date] => 2011-01-03
[end_date] => 2011-06-30
)
[1] => Array
(
[merged_ids] => 18298
[start_date] => 2011-07-09
[end_date] => 2011-10-01
)
)