How to add keys recursively to every array?

Viewed 343

I have this array,

Array (
    [0] => Array (
        [P1] => Array (
            [P2] => Array (
                .
                    .
                        .
                            // n level
            ),
        ),
    ),
    [1] => Array (
        [P4] => Array (
            [P5] => Array (
                .
                    .
                        .
                            // n level
            ),
        ),
    ),
),

I want to convert it into this array

Array (
    [0] => Array (
        'id' => 0
        [P1] => Array (
            'id' => 'P1',
            [P2] => Array (
                    'id' => 'P2'
                .
                    .
                        .
                            // n level
            ),
        ),
    ),
    [1] => Array (
        'id' => '1'
        [P4] => Array (
            'id' => 'P4'
            [P5] => Array (
                'id' => 'P5'
                .
                    .
                        .
                            n level
            ),
        ),
    ),
),

As you can see I took every key and map it to 'id' in its immediate body of an array.

This is effort I tried,

function recursive_function($arr)
{
    $result = [];
    if (is_array($arr)) {
        foreach ($arr as $el) {
            $result = array_merge($result, recursive_function($el));
        }
    } else {
        $result[] = $input;
    }
    return $result;
}

I am new to recursive function and PHP stuff, so unable to think on how to and where to map and why.

Please help me get this output. Any help will be much appreciated.

2 Answers

This is a good programming class homework problem. When writing a recursive function, begin with the case that will end your execution. So, assume that I have my array and I want to "fix" it:

$old; // This is my array;
$new = fix($old); // This takes my old array and gives me a fixed one.

The base case is when my array is empty. If that is case, I just return it and do nothing else.

function fix($a) {
  if(empty($a)) return $a;
}

If it isn't empty, I need to cycle through the elements. If the element is not an array, don't do anything to it.

function fix($a) {
  if(empty($a)) return $a;
  foreach($a as $i=>$v) {
    if(!is_array($v)) // do nothing
  }
}

So, I only want to do something if it $v is an array. What do I want to do? I want to add an index to it that contains the key ($i in my code).

function fix($a) {
  if(empty($a)) return $a;
  foreach($a as $i=>$v) {
    if(is_array($v)) { // Only do something if $v is an array
      $a[$i]['id'] = $i;
    }
  }
}

Almost done. We don't have a recursive call. Because $v was an array, it needs to be fixed as well. That's easy to do:

function fix($a) {
  if(empty($a)) return $a;
  foreach($a as $i=>$v) {
    if(is_array($v)) { // Only do something if $v is an array
      $a[$i] = fix($v);
      $a[$i]['id'] = $i;
    }
  }
}

Now, $v will be fixed and replace it's old self in the array. Then, the id index will be added. But, there is something important to do. We need to return the fixed array!

function fix($a) {
  if(empty($a)) return $a;
  foreach($a as $i=>$v) {
    if(is_array($v)) { // Only do something if $v is an array
      $a[$i] = fix($v);
      $a[$i]['id'] = $i;
    }
  }
  return $a;
}

@kainaw answer is good but this is just simpler version for recursive solution:

function addId(&$arr) {
    foreach($arr as $k => &$v) {
        addId($v);
        $v = array_merge(["id" => $k], $v);
    }
}
$arr = [["P1" => ["P2" => []]], ["P4" => ["P5" => []]]];
addId($arr);

Notice the & which use the data as reference so the original array is changing

Related