user1419810
user1419810

Reputation: 846

Fill 2d array with rows for missing periods of array

I have an array that contains periods from 1 - 13. Sometimes the array doesn't contain data for all periods and I need to fill in the missing ones, for example:

$array = [
    ['period' =>  7, 'y' => 20],
    ['period' =>  8, 'y' => 20.50],
    ['period' =>  9, 'y' => 7020],
    ['period' => 10, 'y' => 6520],
    ['period' => 11, 'y' => 65920],
    ['period' => 12, 'y' => 62820],
    ['period' => 13, 'y' => 6120],
];

For this case I need to run a php loop to fill in the missing first 6 periods with 0 y values. I've tried a variety of loops but with no joy.

Desired output:

[
    ['period' =>  1, 'y' => 0],
    ['period' =>  2, 'y' => 0],
    ['period' =>  3, 'y' => 0],
    ['period' =>  4, 'y' => 0],
    ['period' =>  5, 'y' => 0],
    ['period' =>  6, 'y' => 0],
    ['period' =>  7, 'y' => 20],
    ['period' =>  8, 'y' => 20.50],
    ['period' =>  9, 'y' => 7020],
    ['period' => 10, 'y' => 6520],
    ['period' => 11, 'y' => 65920],
    ['period' => 12, 'y' => 62820],
    ['period' => 13, 'y' => 6120],
]

Upvotes: 1

Views: 82

Answers (6)

mickmackusa
mickmackusa

Reputation: 48031

Use array_column() to generate a lookup array from your input array -- effectively applying associative, numeric, first-level keys without disturbing the original row data.

Then iterate from 1 to 13. If the current iteration's integer is found in the lookup, then push the found row; otherwise push the default row containing the incremented value.

Code: (Demo)

$lookup = array_column($data, null, 'period');
$result = [];
for ($i = 1; $i <= 13; ++$i) {
    $result[] = $lookup[$i] ?? ['period' => $i, 'y' => 0];
}
var_export($result);

Upvotes: 0

simple guy
simple guy

Reputation: 673

Assuming your $array is sorted by period.

You can create a new array that copies the content or your $array and set a new content for missing periods.

$new_array = [];
for ($i = 1, $j = 0; $i <= 13; $i++) {
    if ($array[$j]['period'] == $i) {
        $new_array[] = $array[$j]; //copy contents
        $j++;
    } else { 
        $new_array[] = [ 'period' => $i, 'y' => 0 ]; // set new contents
    }
}

Upvotes: 0

Yoshi
Yoshi

Reputation: 54659

You can get good semantics with using the standard array methods. For example:

<?php
$in = [
    ['period' =>  7, 'y' => 20],
    ['period' =>  8, 'y' => 20.50],
    ['period' =>  9, 'y' => 7020],
    ['period' => 10, 'y' => 6520],
    ['period' => 11, 'y' => 65920],
    ['period' => 12, 'y' => 62820],
    ['period' => 13, 'y' => 6120],
];

// collect available periods
$available = array_column($in, 'period');

// calculate missing periods
$missing = array_diff(range(1, 13), $available);

// transform missing to correct format
$addition = array_map(function ($period) { return ['period' => $period, 'y' => 0]; }, $missing);

// add missing to input
$out = array_merge($in, $addition);

// sort by period
usort($out, function ($a, $b) {
    return $a['period'] <=> $b['period'];
});

// done
print_r($out);

demo: https://3v4l.org/2fDYW

Upvotes: 3

Robin Rai
Robin Rai

Reputation: 392

This should solve your problem:

Let's say $p_array is your array that contains periods from 1 - 13.

// get all periods number that is not missed
$not_missed_periods = array();
foreach ($p_array as $p_each)
{
    $not_missed_periods[] = $p_each['period'];
}
// loop for checking all valid periods i.e 1-13
for ($i=1; $i<=13; $i++)
{
    // check if $i OR period is not in $not_missed_periods
    if (!in_array($i, $not_missed_periods)) {
        $p_array[] = array('period' => $i, 'y' => 0);
    }
}
print_r($p_array);

Upvotes: 0

vijaykumar
vijaykumar

Reputation: 4806

You can try this

for ($i=1 $<=13, $i++) {

   $exits = false;
   foreach ($array as $key => $value) {
        if ($value['period'] == $key) {
           $exits = true;
        }
   }
   if ($exits) {
      $array[] = ['period' => $i , 'y' => 0];
   }
}

Upvotes: 0

Renaud T.
Renaud T.

Reputation: 139

start by filling the whole array you need with all period with a value of 0.

Then for each period you get in your data array, use the period id to update the value of period in the right place in the array.

Hope it helps...

Upvotes: 0

Related Questions