0

I have an associative array, where the keys are datetime type data (with an interval of 15 minutes)

    array:37 [▼
      "09:00" => Appointment {
                    #attributes: array:10 [▼
                        "id" => 1135
                        "startDateTime" => "2019-11-19 09:00:00"
                        "endDateTime" => "2019-11-19 09:45:00"
                        "duration" => 45
                    ]
                  }
      "09:15" => ""     // I want to delete this row -> 15 minutes
      "09:30" => ""     // I want to delete this row -> 30 minutes  end of the appointment
      "09:45" => ""
      "10:00" => Appointment {...duration => 60 ...}
      "10:15" => ""     // I want to delete this row -> 15 minutes
      "10:30" => ""     // I want to delete this row -> 30 minutes
      "10:45" => ""     // I want to delete this row -> 45 minutes
      "11:00" => ""     // I want to delete this row -> 60 minutes end of the appointment
      "11:15" => ""
      "11:30" => ""
      "11:45" => "" Appointment {...duration => 15 ...}
       ...
    ]

This array will feed a table, so I want to delete the subsequent rows based on the duration of each appointment. I need it because i want to span the appointment over several rows with:

<td class="the-appointment" rowspan="{{ $appointment->duration / 15 }}">...

therefore I need to eliminate the subsequent rows from the array.

I did this:

    $index = -1;
    foreach ($row as  $key => $appointment) {
        if ($appointment) {
            $loops = $appointment->duration / 15;
        }
        for ($i = 1; $i < $loops; $i++) {
            unset($row[$index + 1]);
            $index++;
        }
    }

    array_push($calendar, $row);

But since it is an associative array, I can not get the index of the loop. Is there any cleverer way to do this?

1
  • array_keys and use these keys as values. array_splice is another solution, no keys needed. Commented Nov 17, 2019 at 13:39

2 Answers 2

1

Rather than using foreach(), you can use for() and use the duration to skip the entries you don't need. The result is put into $slots.

Basically, loop over the times in the slots and if the duration is set, then increment the loop counter by the length of the appointment (duration/15 and use ceil() to round it up)...

$row = ["09:00" => (object)["duration" => 40],
    "09:15" => "",
    "09:30" => "",
    "09:45" => "",
    "10:00" => (object)["duration" => 60],
    "10:15" => "",
    "10:30" => "",
    "10:45" => "",
    "11:00" => "",
    "11:15" => "",
    "11:30" => "",
    "11:45" => (object)["duration" => 45]
];

$slots = [];
$times = array_keys($row);
for ( $i = 0; $i < count($times); $i++  )    {
    $appointment = $row[$times[$i]];
    $slots[$times[$i]] = $appointment;
    if ( $appointment->duration ?? 0 > 0 )  {
        $i += ceil($appointment->duration / 15);
    }
}
print_r($slots);

with the test data, this gives...

(
    [09:00] => stdClass Object
        (
            [duration] => 40
        )

    [10:00] => stdClass Object
        (
            [duration] => 60
        )

    [11:15] => 
    [11:30] => 
    [11:45] => stdClass Object
        (
            [duration] => 45
        )

)
Sign up to request clarification or add additional context in comments.

1 Comment

Hi thanks for the solution. I was just changing a detail in this line: $i += ceil($appointment->duration / 15). the soluution is jumping one slot too much. If an appointment starts at 10:00 and has 45 minutes duration; the following slots should starts on 10:45. So I just substract 1 unit in the line $i += ceil($appointment->duration / 15 - 1); and the results is perfect. Thanks for the help!!
1

Some piece of code to start with:

$duration = 0;
// I suggest to use array_filter and track `$duration` on each loop
$filtered = array_filter(
    $apps,
    function ($apm) use (&$duration) {
        if ($duration === 0) {
            if (!empty($apm->duration)) {
                $duration = $apm->duration - 15;
                return true;
            } else {
                return true;
            }
        } else {
            $duration -= 15;
            return false;    
        }
    }
);

Working fiddle here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.