Push a static associative element into all subarrays on a known level with a known parent key

88 Views Asked by At

I have a dynamically generated PHP multi-dimensional array as follows:

Array (
    [uid_1] => Array (
        [sub_1] => Array (
            [sub_sub_1] => Array (
                [id1] => "val_1",
                [id2] => "val_2"
            )
        )
        [sub_2] => Array (
            [sub_sub_1] => Array (
                [id1] => "val_1",
                [id2] => "val_2"
            ),
            [sub_sub_2] => Array (
                [id3] => "val_3",
                [id4] => "val_4"
            )
        )
    )
)

The array is much bigger and will contain multiple [uid], [sub] and [sub_sub].
Note that while [uid] and [sub] are unique, [sub_sub] are not.

Is it possible to add [id5] => "val_5" to all instances of [sub_sub_1] without using loops and without knowing the value of [uid_1] and [sub_2]?

4

There are 4 best solutions below

0
Jenson M John On

Since You mentioned The array is much bigger, Loop may be needed.

    <?php
    $mainArray = array (
        "uid_1" => array (
            "sub_1" => array (
                "sub_sub_1" => array (
                    "id1" => "val_1",
                    "id2" => "val_2"
                )
                ),
            "sub_2" => array (
                "sub_sub_1" => array (
                    "id1" => "val_1",
                    "id2" => "val_2"
                ),
                "sub_sub_2" => array (
                    "id3" => "val_3",
                    "id4" => "val_4"
                )
            )
        )
    );

    echo "<pre>";
    print_r( $mainArray );
    echo "</pre>";



    foreach($mainArray["uid_1"] as $key=>$val){
        
        //$val (Arrays with index 'sub_1', 'sub_2' etc.)
        //Get array with index 'sub_sub_1' & Assign a New Value with key `id5`.

        $mainArray["uid_1"][$key]['sub_sub_1']["id5"] = "val_5";


    }

    echo "<pre>";
    print_r( $mainArray );
    echo "</pre>";
    ?>
1
Ishtiaq Ahmed On

Try the following code.

<?php
$mainArray = array(
    "uid_1" => array(
        "sub_1" => array(
            "sub_sub_1" => array(
                "id1" => "val_1",
                "id2" => "val_2"
            )
        ),
        "sub_2" => array(
            "sub_sub_1" => array(
                "id1" => "val_1",
                "id2" => "val_2"
            ),
            "sub_sub_2" => array(
                "id3" => "val_3",
                "id4" => "val_4"
            )
        )
    )
);

echo "<pre>";
print_r($mainArray);
echo "</pre>";

foreach ($mainArray["uid_1"] as $key => $val) {

    // Check if 'sub_sub_1' exists before trying to access it
    if (isset($mainArray["uid_1"][$key]['sub_sub_1'])) {
        // Get array with index 'sub_sub_1' & Assign a New Value with key `id5`.
        $mainArray["uid_1"][$key]['sub_sub_1']["id5"] = "val_5";
    }
}

echo "<pre>";
print_r($mainArray);
echo "</pre>";
?>
0
lukas.j On
$array = [
  'uid_1' => [
    'sub_1' => [
      'sub_sub_1' => [ 'id1' => 'val_1', 'id2' => 'val_2' ]
    ],
    'sub_2' => [
      'sub_sub_1' => [ 'id1' => 'val_1', 'id2' => 'val_2' ],
      'sub_sub_2' => [ 'id3' => 'val_3', 'id4' => 'val_4' ]
    ]
  ],
  'uid_2' => [
    'sub_1' => [
      'sub_sub_1' => [ 'id1' => 'val_1', 'id3' => 'val_3' ]
    ],
  ]
];

$iterator = new RecursiveIteratorIterator(
  new RecursiveArrayIterator($array),
  RecursiveIteratorIterator::SELF_FIRST
);
$iterator->setMaxDepth(2);

while ($it->valid()) {
  if ($it->key() === 'sub_sub_1') {
    $array[$it->getSubIterator(0)->key()][$it->getSubIterator(1)->key()]['sub_sub_1']['id5'] = 'val_5';
  }
  $it->next();
}

print_r($array);

Output:

Array
(
    [uid_1] => Array
        (
            [sub_1] => Array
                (
                    [sub_sub_1] => Array
                        (
                            [id1] => val_1
                            [id2] => val_2
                            [id5] => val_5
                        )

                )

            [sub_2] => Array
                (
                    [sub_sub_1] => Array
                        (
                            [id1] => val_1
                            [id2] => val_2
                            [id5] => val_5
                        )

                    [sub_sub_2] => Array
                        (
                            [id3] => val_3
                            [id4] => val_4
                        )

                )

        )

    [uid_2] => Array
        (
            [sub_1] => Array
                (
                    [sub_sub_1] => Array
                        (
                            [id1] => val_1
                            [id3] => val_3
                            [id5] => val_5
                        )

                )

        )

)

Notes:

The RecursiveArrayIterator visits every top node of the array. The RecursiveIteratorIterator wraps the RecursiveArrayIterator and will visit every node of the array, not just the top nodes. And setMaxDepth makes sure we do not waste time visiting nodes more than three level deep.

We iterate, check for the key being 'sub_sub_1', and if true, we grab the parent path parts with getSubIterator->key calls. And then we just create the key and assign the value.

0
mickmackusa On

Don't bother trying to make a simple task more complicated. Using functions to iterate is likely to take longer and be harder to understand.

Use two nested loops which modify the data sets by reference and unconditionally push your desired associative element where required.

Even if a data set (subarray) doesn't have a sub_sub_1 level, this script will create the level and safely push the required element into it. If this is not the desired behavior, then you should provide a more representative sample input array and express how this fringe case should be handled.

Code: (Demo)

foreach ($array as &$uids) {
    foreach ($uids as &$subs) {
        $subs['sub_sub_1']['id5'] = 'val_5';
    }
}
var_export($array);

Output:

array (
  'uid_1' => 
  array (
    'sub_1' => 
    array (
      'sub_sub_1' => 
      array (
        'id1' => 'val_1',
        'id2' => 'val_2',
        'id5' => 'val_5',
      ),
    ),
    'sub_2' => 
    array (
      'sub_sub_1' => 
      array (
        'id1' => 'val_1',
        'id2' => 'val_2',
        'id5' => 'val_5',
      ),
      'sub_sub_2' => 
      array (
        'id3' => 'val_3',
        'id4' => 'val_4',
      ),
    ),
  ),
  'uid_2' => 
  array (
    'sub_1' => 
    array (
      'sub_sub_1' => 
      array (
        'id1' => 'val_1',
        'id3' => 'val_3',
        'id5' => 'val_5',
      ),
    ),
  ),
)