php - Check entire array for sub array with two values? -
i have mixed array made of events. example:
array ( [0] => array ( [start] => 20:00 [end] => 21:00 [title] => test event date [date] => 22 jun 2014 ) [1] => array ( [start] => 20:00 [end] => 22:00 [title] => test event without date [day] => sunday ) )
most events daily (e.g. sunday). however, occasional , have full date.
if event full date falls on same day , time daily event (as in example above), daily event not show when step through array in foreach.
is there way check if both date , time exist in item somewhere else in array before outputting?
this have far:
// loop through each day of week foreach ($thisweek $day => $v) { echo '<h3>' . $day . ' ' . $v . '</h3>'; echo '<ul>'; // loop through bunch of hours foreach ($eventhours $eventhour) { // loop through events foreach ($mergedevents $event) { // if event date on day / hour if ($event['date'] == $v && $event['start'] == $eventhour) { echo '<li><strong>' . $eventhour . ' - ' . $event['title'] . '</strong></li>'; } // if daily event has day / hour if ($event['day'] == $day && $event['start'] == $eventhour) { echo '<li>' . $eventhour . ' - ' . $event['title'] . '</li>'; }; } } echo '</ul>'; }
this works fine, both occasional , daily events show regardless. guess need wrap if($event['day'] == $day)
part in if looks through whole array. possible how?
tested code on php 5.3.18. later version functions , includes sort , reduction simple output array
download source code updated version sort function.
demonstration of code shown below @ viper-7
required: given 2 events same day, 1 specific date , 1 repeats on day, event specific date must used.
check time of events day non-overlapping events accepted , preference given 'run-once' events.
assumptions: input 1 week. order of events in input not important.
the output array dependent on order of input. i.e. not in day order.
the time of events must taken account when adding events.
the algorithm: there lots of comments in code explaining actual checks performed. not simple thought initially.
run once event: must not overlap other event day , added on similar 'repeat' event day.
repeated events: add output if output day / time empty. these overwritten 'specific date' events same day / time.
code:
/* * hold list of events day. * each 'day' list of non-overlapping events. */ $weekevents = array(); // output events here // process each event 'day' , 'time'... foreach($events $newevent) { $neweventisrunonce = false; // make testing easier read later. // add 'day' entry run_once events if (!empty($newevent['date'])) { $dt = datetime::createfromformat('d m y', $newevent['date']); $day = $dt->format('l'); $newevent = array_merge($newevent, array('day' => $day)); $neweventisrunonce = true; } // see if can added event list... if (!isset($weekevents[$newevent['day']])) { // nothing today add $weekevents[$newevent['day']][] = $newevent; continue; // next event... } // check whether 'newevent' overlaps events today in list. // 1) may need replace entry curentry new 1 // 2) may overlap more 1 entry! $overlapcount = 0; $overlapcurentryidx = -1; $overlapcurisrunonce = false; // makes testing easier read later foreach ($weekevents[$newevent['day']] $idx => $curevent) { if (timerangeoverlap($curevent['start'], $curevent['end'], $newevent['start'], $newevent['end'])) { $overlapcount++; $overlapcurentryidx = $idx; $overlapcurisrunonce = !empty($curevent['date']); } } // check see if overlaps if ($overlapcount === 0) { // ok add $weekevents[$newevent['day']][] = $newevent; continue; // next event... } // check see if overlaps , type overlaps with... if ($overlapcount === 1) { // overlaps 1 event if (!$overlapcurisrunonce && $neweventisrunonce) { $weekevents[$newevent['day']][$overlapcurentryidx] = $newevent; } continue; // next event... } } echo '<pre>'; print_r($weekevents);
time range overlap function:
/* * need calculate whether 2 time ranges overlap. * time entered hh:mm in 24 hour format. * * not efficient routine easy check works */ function timerangeoverlap($r1start, $r1end, $r2start, $r2end) { // convert times can compared easily. $r1start = strtotime($r1start); $r1end = strtotime($r1end); $r2start = strtotime($r2start); $r2end = strtotime($r2end); // order them earliest start time can see works. // $r1 contain earliest start time if ($r1start <= $r2start) { $r1 = array('s' => $r1start, 'e' => $r1end); $r2 = array('s' => $r2start, 'e' => $r2end); } else { $r1 = array('s' => $r2start, 'e' => $r2end); $r2 = array('s' => $r1start, 'e' => $r1end); } // ensure not overlap // in words: r1 ends before r2 starts or r1 starts after r2 ends if ($r1['e'] <= $r2['s'] || $r1['s'] >= $r2['e']) { return false; } return true; }
test data:
$events = array( array('start' => '20:00', 'end' => '21:00', 'title' => 'event1: run_once', 'date' => '22 jun 2014'), array('start' => '20:00', 'end' => '22:00', 'title' => 'event1: repeat', 'day' => 'sunday'), array('start' => '10:00', 'end' => '12:00', 'title' => 'event2 : repeat', 'day' => 'sunday'), array('start' => '9:00', 'end' => '11:00', 'title' => 'event2 : run_once', 'date' => '22 jun 2014'), array('start' => '15:00', 'end' => '17:00', 'title' => 'event3 : repeat', 'day' => 'sunday'), );
Comments
Post a Comment