1

I have this multidimensional array in PHP:

Array
(
    [47] => Array
        (
            [2019-02-24] => Array
                (
                    [AVA_Id] => 1
                    [AVA_Status] => Open
                )
            [2019-02-25] => Array
                (
                    [AVA_Id] => 3
                    [AVA_Status] => Open
                )
            [2019-02-28] => Array
                (
                    [AVA_Id] => 4
                    [AVA_Status] => Close
                )
        )
    [48] => Array
        (
            [2019-02-26] => Array
                (
                    [AVA_Id] => 2
                    [AVA_Status] => Open
                )
        )
)

How for a known date range I can fill this array with missing dates ?

My date range is the following:

Array ( [0] => 2019-02-24 [1] => 2019-02-25 [2] => 2019-02-26 [3] => 2019-02-27 [4] => 2019-02-28 [5] => 2019-03-01 [6] => 2019-03-02 )

For example, for array wit the key 47, I would need to add missing date: 2019-02-26, 2019-02-27, 2019-03-01 and 2019-03-02 because these dates are into the range of dates but not into the array under the key 47. Same thing for the key 48.

My try was this one:

foreach($daterange as $date){
    $date = $date->format('Y-m-d');
    if(in_array($myarray[$date]))
        $newarray[$date] = $myarray[$date];
    else
        $newarray[$date] = 0;
}
3
  • What values (AVA_Id and AVA_Status) do you want to add for the missing dates, or do you just want an empty array? Commented Feb 24, 2019 at 22:20
  • Hello @Nick, AVA_Id could be 0 and AVA_Status could be no. Thanks for your help. Commented Feb 24, 2019 at 22:22
  • instead of in_array use isset. Commented Feb 24, 2019 at 22:26

2 Answers 2

2

Basically you need to loop through each element of your array, and then check whether each date is present as a key in the array. If it isn't, we add a "blank" element for that date:

foreach ($array as &$arr) {
    foreach ($dates as $date) {
        if (!in_array($date, array_keys($arr))) {
            $arr[$date] = array('AVA_Id' => 0, 'AVA_Status' => 'no');
        }
    }
}
print_r($array);

The output is quite long so I've omitted it but you can see it in this demo on 3v4l.org

To sort the array keys by date, just add a ksort to the loop:

foreach ($array as &$arr) {
    foreach ($dates as $date) {
        if (!in_array($date, array_keys($arr))) {
            $arr[$date] = array('AVA_Id' => 0, 'AVA_Status' => 'no');
        }
    }
    ksort($arr);
}

demo on 3v4l.org

Update

As pointed out in the comments by @trincot, the above can be written more efficiently using isset rather than in_array:

foreach ($array as &$arr) {
    foreach ($dates as $date) {
        $arr[$date] = isset($arr[$date]) ? $arr[$date] : array('AVA_Id' => 0, 'AVA_Status' => 'no');
    }
    ksort($arr);
}

Demo on 3v4l.org

Or using the NULL coalescing operator ?? in PHP7 upwards:

foreach ($array as &$arr) {
    foreach ($dates as $date) {
        $arr[$date] = $arr[$date] ?? array('AVA_Id' => 0, 'AVA_Status' => 'no');
    }
    ksort($arr);
}

Demo on 3v4l.org

Update 2

The code can be made even more efficient by using a temporary array in the loop, which removes the need for ksort:

foreach ($array as &$arr) {
    foreach ($dates as $date) {
        $out[$date] = $arr[$date] ?? array('AVA_Id' => 0, 'AVA_Status' => 'no');
    }
    $arr = $out;
}

Demo on 3v4l.org

Note

As has been pointed out by @dWinder, you can use array_diff between the $dates array and the keys of each array element to find the new entries that are required:

foreach ($array as &$arr) {
    foreach (array_diff($dates, array_keys($arr)) as $date) {
        $arr[$date] = array('AVA_Id' => 0, 'AVA_Status' => 'no');
    }
    ksort($arr);
}

Demo on 3v4l.org

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

15 Comments

I would prefer use array_diff to get the key to set
@dWinder good idea! If you don't plan to add that as an answer I'll include it in mine?
Go ahead - you answer is good - I prefer 1 great answer then 3 separate. And add also ksort
@dWinder I was 14 seconds ahead of you on the ksort! :-)
@lufc agreed. To be fair though, there isn't really that much of a need to ksort as it just makes the data prettier for display. Any attempt to access the array elements via a given date index will work regardless of whether the keys are sorted or not.
|
1

Why not start with a blank array of date ranges and then copy your actual elements into this array.

$template = array_fill_keys($daterange,['AVA_Id' => 0,'AVA_Status' => 'No']);

foreach ($outer as $ind => $dates) {

   $output[$ind] = $template;

   foreach ($dates as $d => $v) {

       $output[$ind][$d] = $v;

   }

 }

Demo on 3v4l.org

3 Comments

@PacPac if you have a big dataset it would be worth benchmarking this answer against mine you might well find it is faster.
Hello lufc, do I need to use ksort() function to sort the dates ASC ?
No you do not need to ksort as your $daterange was already sorted and this maintains that ordering. This is also much more efficient than the accepted answer.

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.