patternphpMinor
Get ranges from array of days
Viewed 0 times
arrayrangesgetfromdays
Problem
I have an array of dates as input in the form "YYYY-mm-dd"=>category_id.0 (category_id counting from 0).
I want to build an array of range of dates grouped by category_id.
For example,
`array('
$days =array (
'2014-10-15' => 49,
'2014-10-16' => 49,
'2014-10-17' => 49,
'2014-10-18' => 0,
'2014-10-19' => 0,
'2014-10-20' => 0,
'2014-10-21' => 0,
'2014-10-22' => 0,
'2014-10-23' => 0,
'2014-10-24' => 0,
'2014-10-25' => 0,
'2014-10-26' => 0,
'2014-10-27' => 0,
'2014-10-28' => 0,
'2014-10-29' => 0,
'2014-10-30' => 0,
'2014-10-31' => 0,
'2014-11-01' => 0,
'2014-11-02' => 0,
/* MISSING 2014-11-03 */
'2014-11-04' => 0,
'2014-11-05' => 0,
'2014-11-06' => 0,
'2014-11-07' => 0,
'2014-11-08' => 0,
'2014-11-09' => 0,
'2014-11-10' => 0,
'2014-11-11' => 0,
'2014-11-12' => 0,
'2014-11-13' => 0,
'2014-11-14' => 0,
'2014-11-15' => 0,
'2014-11-16' => 0,
'2014-11-17' => 0,
'2014-11-18' => 0,
'2014-11-19' => 0,
'2014-11-20' => 0,
'2014-11-21' => 0,
'2014-11-22' => 0,
'2014-11-23' => 0,
'2014-11-24' => 0,
'2014-11-25' => 0,
'2014-11-26' => 0,
'2014-11-27' => 0,
'2014-11-28' => 0,
'2014-11-29' => 0,
'2014-11-30' => 0,
'2014-12-01' => 0,
'2014-12-02' => 0,
'2014-12-03' => 0,
'2014-12-04' => 0,
'2014-12-05' => 0,
'2014-12-06' => 0,
'2014-12-07' => 0,
'2014-12-08' => 0,
'2014-12-09' => 0,
'2014-12-10' => 0,
'2014-12-11' => 0,
'2014-12-12' => 0,
'2014-12-13' => 0,
'2014-12-14' => 0,
'2014-12-15' => 0,
'2014-12-16' => 0,
'2014-12-17' => 0,
'2014-12-18' => 0,
'2014-12-19' => 0,
'2014-12-20' => 0,
'2014-12-21' => 0,
'2014-12-22' => 1,
'2014-12-23' => 3,
'2014-12-24' => 3,
'2014-12-25' => 3,
'2014-12-26' => 3,
'2014-12-27' => 3,
'2014-12-28' => 3,
'2014-12-29' => 50,
'2014-12-30' => 50,
'2014-12-31' => 50,
'2015-12-24' => 2,
'2015-12-25' => 2,
);I want to build an array of range of dates grouped by category_id.
For example,
category_id 49 has 3 consecutive days from 15 to 17, so the first range should be:`array('
Solution
This is the way I would do it:
I use an intermediate array which makes it easier to get the results because it's already segmented by catagory. All that's then left to do is the date ranges. I turn dates into seconds to see if the gap is bigger than one day (> 99999 seconds).
function getRangeFromDays($days) {
// collect dates into catagories
foreach ($days as $date => $catagory) {
$temp[$catagory][] = $date;
}
// process all dates in each catagory
foreach ($temp as $catagory => $dates) {
sort($dates);
$startDate = $dates[0];
$finishDate = array_pop($dates);
// walk through the dates, breaking at gaps
foreach ($dates as $key => $date)
if (($key > 0) && (strtotime($date)-strtotime($dates[$key-1]) > 99999)) {
$result[] = array($startDate,$dates[$key-1],$catagory);
$startDate = $date;
}
// force the end
$result[] = array($startDate,$finishDate,$catagory);
}
return $result;
}
echo '';
print_r(getRangeFromDays($days));
echo '';I use an intermediate array which makes it easier to get the results because it's already segmented by catagory. All that's then left to do is the date ranges. I turn dates into seconds to see if the gap is bigger than one day (> 99999 seconds).
Code Snippets
function getRangeFromDays($days) {
// collect dates into catagories
foreach ($days as $date => $catagory) {
$temp[$catagory][] = $date;
}
// process all dates in each catagory
foreach ($temp as $catagory => $dates) {
sort($dates);
$startDate = $dates[0];
$finishDate = array_pop($dates);
// walk through the dates, breaking at gaps
foreach ($dates as $key => $date)
if (($key > 0) && (strtotime($date)-strtotime($dates[$key-1]) > 99999)) {
$result[] = array($startDate,$dates[$key-1],$catagory);
$startDate = $date;
}
// force the end
$result[] = array($startDate,$finishDate,$catagory);
}
return $result;
}
echo '<pre>';
print_r(getRangeFromDays($days));
echo '</pre>';Context
StackExchange Code Review Q#82989, answer score: 7
Revisions (0)
No revisions yet.