duandushang5148 2014-06-25 23:28
浏览 8
已采纳

使用两个值检查整个数组的子数组?

I have a mixed array made up of events. Example:

 Array
(
    [0] => Array
        (
            [start] => 20:00
            [end] => 21:00
            [title] => test event with a date
            [date] => 22 Jun 2014
        )

    [1] => Array
        (
            [start] => 20:00
            [end] => 22:00
            [title] => test event without a date
            [day] => Sunday
        )

)

Most events are daily (e.g. Sunday). However, some are occasional and have a full date.

If an event with a full date falls on the same day and time as a daily event (as in the example above), I would like the daily event not to show up when I step through the array in a foreach.

Is there a way to check if both the date and time exist in an item somewhere else in the array before outputting?

This is what I have so far:

// loop through each day of week
    foreach ($thisweek as $day => $v) {
        echo '<h3>' . $day . ' ' . $v . '</h3>';
        echo '<ul>';
        // loop through a bunch of hours
        foreach ($eventhours as $eventhour) {
            // loop through events
            foreach ($mergedevents as $event) {

                // if event date is on this day / hour
                if ($event['date'] == $v && $event['start'] == $eventhour) {
                        echo '<li><strong>' . $eventhour . ' - ' . $event['title'] . '</strong></li>';
                } 

                // if daily event has this day / hour
                if ($event['day'] == $day && $event['start'] == $eventhour) {
                        echo '<li>' . $eventhour . ' - ' . $event['title'] . '</li>';
                };

            }
        }
        echo '</ul>';
    }

This works fine, but both occasional and daily events show up regardless. I guess I need to wrap the if($event['day'] == $day) part in another if that looks through the whole array. Is that possible some how?

  • 写回答

2条回答 默认 最新

  • dongqichang7988 2014-06-26 03:26
    关注

    Tested code on PHP 5.3.18. later version where everything is functions and includes a sort and reduction to a simple output array

    Download the source code for the updated version with the sort function.

    demonstration of the code shown below at viper-7

    Required: Given two events for the same day, one specific to the date and one the repeats on the day, then the event with specific date must be used.

    Check the time of the events for any day so that only non-overlapping events are accepted and preference is given to 'run-once' events.

    Assumptions: the input is for one week. The order of the events in the input is not important.

    The output array will be dependent on the order of the input. i.e. it is not certain to be in day order.

    The time of the events must be taken into account when adding events.

    The algorithm: There are lots of comments in the code explaining the actual checks performed. It is not as simple as i thought initially.

    Run Once Event: This must not overlap with any other event for the day and is added over any similar 'repeat' event for the day.

    repeated events: only add to output if output day / time is empty. These will get overwritten by 'specific date' events for the same day / time.

    Code:

    /*
     * Hold a list of events by day.
     * Each 'day' will be a list of non-overlapping events.
     */
    $weekEvents = array(); // output events here
    
    // process each event which is 'day' and 'time'... 
    foreach($events as $newEvent) {
        $newEventIsRunOnce = false; // make testing easier to read later.
    
        // add a 'day' entry to 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;
        }
    
        // now see if it can be added to the event list...
    
        if (!isset($weekEvents[$newEvent['day']])) { // nothing for today so add
            $weekEvents[$newEvent['day']][] = $newEvent;
            continue; // do the next event...
        }
    
        // now check whether the 'newEvent' overlaps with any events for today in the list.
        // 1) may need to replace the entry with the curEntry with the new one
        // 2) it may overlap more than one entry!
    
        $overlapCount = 0;
        $overlapCurEntryIdx = -1;
        $overlapCurIsRunOnce = false; // makes testing easier to read later
        foreach ($weekEvents[$newEvent['day']] as $idx => $curEvent) {
            if (timeRangeOverlap($curEvent['start'], $curEvent['end'],
                                  $newEvent['start'], $newEvent['end'])) {
               $overlapCount++;
               $overlapCurEntryIdx = $idx;
               $overlapCurIsRunOnce = !empty($curEvent['date']);
            }
        }
    
        // now check to see if overlaps any
        if ($overlapCount === 0) { // ok to add
            $weekEvents[$newEvent['day']][] = $newEvent;
            continue; // do the next event...
        }
    
        // now check to see if overlaps and what type it overlaps with...
        if ($overlapCount === 1) { // only overlaps one event
            if (!$overlapCurIsRunOnce && $newEventIsRunOnce) {
                $weekEvents[$newEvent['day']][$overlapCurEntryIdx] = $newEvent;
            }
            continue; // do the next event...
        }
    }
    
    echo '<pre>';
    print_r($weekEvents);
    

    Time Range Overlap Function:

    /*
     *  need to calculate whether two time ranges overlap.
     *  A time will always be entered as hh:MM in 24 hour format.
     *
     * This is not the most efficient routine but is easy to check that it works
     */
    function timeRangeOverlap($r1Start, $r1End, $r2Start, $r2End)
    {
        // convert all to times that can be compared easily.
        $r1Start = strtotime($r1Start); $r1End = strtotime($r1End);
        $r2Start = strtotime($r2Start); $r2End = strtotime($r2End);
    
        // order them by earliest start time so i can easily see that it works.
        // $r1 will always contain the 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 they do 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'),
    );
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题