user5249203
user5249203

Reputation: 4648

fill in the multidimensional array with missing keys

I have the following multidimensional array. I had to create keys the way it looks to group them accordingly.

Array
(
    [Oranges] => Array
        (
            [Name] => Oranges
            [l.VA123] => 17
            [l.MA123] => 12
            [l.GA123] => 9
            [l.CT123] => 5
        )

    [Apple] => Array
        (
            [Name] => Apple
            [l.CA123] => 13
        )

    [Grapes] => Array
        (
            [Name] => Grapes
            [l.WI123] => 8
            [l.FL123] => 5
        )
)

However, I need all the subarrays to have the same keys. Missing ones should be filled with a value of 0. The final array should be like below so that all subarrays have equal length.

    Array
(
    [Oranges] => Array
        (
            [Name] => Oranges
            [l.VA123] => 17
            [l.MA123] => 12
            [l.GA123] => 9
            [l.CT123] => 5
            [l.CA123] => 0
            [l.WI123] => 0
            [l.FL123] => 0
        )

    [Apple] => Array
        (
            [Name] => Apple
            [l.CA123] => 13
            [l.WI123] => 0
            [l.FL123] => 0
            [l.VA123] => 0
            [l.MA123] => 0
            [l.GA123] => 0
            [l.CT123] => 0
        )

    [Grapes] => Array
        (
            [Name] => Grapes
            [l.WI123] => 8
            [l.FL123] => 5
            [l.CA123] => 0
            [l.VA123] => 0
            [l.MA123] => 0
            [l.GA123] => 0
            [l.CT123] => 0
        )
)

Upvotes: 3

Views: 1094

Answers (3)

mickmackusa
mickmackusa

Reputation: 47991

Since all keys and default values are "known", create an associative array, use a foreach() and modify the rows by reference, and use the union-assignment (combined) operator. This will allow the original values to overwrite the default values.

Code: (Demo)

$keys = [
    'l.VA123' => 0,
    'l.MA123' => 0,
    'l.GA123' => 0,
    'l.CT123' => 0,
    'l.CA123' => 0,
    'l.WI123' => 0,
    'l.FL123' => 0,
];

foreach ($items as &$row) {
    $row += $keys;
}
var_export($items);

If you want the keys to be consistently positioned, then use array_replace() or array_merge() instead of the union assignment operator.

Code: (Demo)

foreach ($items as &$row) {
    $row = array_replace($keys, $row);
}

Upvotes: 1

u_mulder
u_mulder

Reputation: 54831

You need a simple + operator. As from manual:

The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.

$items = Array
(
    'Oranges' => Array
        (
            'Name' => 'Oranges',
            'l.VA123' => 17,
            'l.MA123' => 12,
            'l.GA123' => 9,
            'l.CT123' => 5,
        ),

    'Apple' => Array
        (
            'Name' => 'Apple',
            'l.CA123' => 13,
        ),

    'Grapes' => Array
        (
            'Name' => 'Grapes',
            'l.WI123' => 8,
            'l.FL123' => 5,
        ),
);

// static keys
$keys = [
    'l.VA123' => 0,
    'l.MA123' => 0,
    'l.GA123' => 0,
    'l.CT123' => 0,
    'l.CA123' => 0,
    'l.WI123' => 0,
    'l.FL123' => 0,
];


// keys generated from source array, tricky approach
$keys = array_fill_keys(
    // here we merge all elements of `$items` into one array
    // as keys are repeated - you definitely got all keys that
    // can be in `$items`, `array_keys` will give you these keys
    // `array_fill_keys` will create array where key is what you need
    // and value is 0.
    array_keys(call_user_func_array('array_merge', $items)),
    0
);

// keys generated from source array, SIMPLE approach
$keys = [];
foreach ($items as $item) {
    foreach ($item as $k => $v) {
        if ($k != 'Name') {
            $keys[$k] = 0;
        }
    }
}

foreach ($items as &$item) {
    $item = $item + $keys;
}
print_r($items);

Upvotes: 4

miken32
miken32

Reputation: 42717

Probably someone can come up with something more efficient, but without a list of keys that you want, I think you'll need to take a couple of passes of the array:

<?php
$fruits = [
    "Oranges"=>["Name"=>"Oranges", "l.VA123"=>17, "l.MA123"=>12, "1.GA123"=>9, "1.CT123"=>5],
    "Apple"=>["Name"=>"Apple", "1.CA123"=>13],
    "Grapes"=>["Name"=>"Grapes", "1.WI123"=>8, "1.FL123"=>5]
];
$keys = [];
foreach ($fruits as $fruit) {
    unset($fruit["Name"]);
    $keys = array_merge($keys, array_keys($fruit));
}
$keys = array_fill_keys(array_unique($keys), 0);

foreach ($fruits as &$fruit) {
    $fruit = array_merge($keys, $fruit);
}
print_r($fruits);

Upvotes: 2

Related Questions