Thursday, 30 August 2018

PHP - How to recursively copy associative array elements to another array element?

I have an associative array with keys that are numbered like software release version numbers, for example 32.1, what I want to do is take each of the versions following 32.1 (32.2, 32.3, 32.4, etc) and assign them to another array under the 32 key, more so I need the script to be recursive, so that longer version numbers with multiple releases end up in the correct array keys.

My code...
<?php

    $array = array(
        '1' => 'Level 1',
        '1-1' => 'Level 1',
        '1-2' => 'Level 1',
        '1-2-1' => 'Sub-Level 1',
        '2' => 'Level 2',
        '3' => 'Level 3'
    );

    foreach ($array as $key => $value) {
        static $assoc = array();

        if (preg_match('/-/', $key)) {
            $points = explode('-', $key);
            $assoc_key = basename($key, '-' . end($points));
            $assoc[$assoc_key]['sub'][$key] = array('1' => 'Sub-' . $array[end($points)]);
        } else {
            $assoc[$key] = array('1' => $array[$key]);
        }
    }

    echo '<pre>' . print_r($assoc, true) . '</pre>';

?>

Expected Output:
Array
(
  [1] => Array
    (
      [1] => Level 1
      [sub] => Array
        (
          [1-1] => Array
            (
              [1] => Sub-Level 1
            )

          [1-2] => Array
            (
              [1] => Sub-Level 2
              [sub] => Array
                (
                  [1-2-1] => Array
                    (
                      [1] => Sub-Sub-Level 1
                    )

                )

            )

        )

    )

  [2] => Array
    (
      [1] => Level 2
    )

  [3] => Array
    (
      [1] => Level 3
    )

)

Actual Output
Array
(
  [1] => Array
    (
      [1] => Level 1
      [sub] => Array
        (
          [1-1] => Array
            (
              [1] => Sub-Level 1
            )

          [1-2] => Array
            (
              [1] => Sub-Level 2
            )

        )

    )

  [1-2] => Array
    (
      [sub] => Array
        (
          [1-2-1] => Array
            (
              [1] => Sub-Level 1
            )

        )

    )

  [2] => Array
    (
      [1] => Level 2
    )

  [3] => Array
    (
      [1] => Level 3
    )

)

Can anyone help?
I just know it's something simple I'm missing, but I've been trying to get this to work for two days now.

I came up with something that could solve your problem using array references.
Probably the code can be further optimized as well, but should be enough to show the concept.
As you stated, the function has to be recursive, but you used an iterative approach.
<?php
  $array = array(
    '1' => 'Level 1',
    '1-1' => 'Level 1',
    '1-2' => 'Level 1.2',
    '1-2-1' => 'Level 1.2.1',
    '2' => 'Level 2',
    '3' => 'Level 3'
  );

  $assoc = array();

  foreach ($array as $key => $value) {
    if (strpos($key, "-") !== false) {
      $points  = explode('-', $key);
      $current = &$assoc[$points[0]];
      $str     = $points[0];
      for ($i = 1; $i < count($points); $i++) {
        $str    .= "-" . $points[$i];
        if (!isset($current["sub"]))
          $current["sub"] = array();
        $current = &$current["sub"][$str];
      }
      $current[1] = 'Sub-' . $value;
    }
    else {
      $assoc[$key][1] = $array[$key];
    }
  }

  echo '<pre>' . print_r($assoc, true) . '</pre>';
?>

0 comments:

Post a Comment