0

I have been trying to get this to work for 7.5 hours now, but my brain has melted.

I have a multi-dimensional array similar to the following:

array (
  'expanded' => true,
  'key' => 'root_1',
  'title' => 'root',
  'children' => 
  array (
    0 => 
    array (
      'folder' => false,
      'key' => '_1',
      'title' => 'News',
      'data' => 
      array (
        'id' => '3',
        'parent_id' => 0,
      ),
    ),
    1 => 
    array (
      'folder' => true,
      'key' => '_2',
      'title' => 'Animations',
      'data' => 
      array (
        'id' => '5',
        'parent_id' => '0',
      ),
      'children' => 
      array (
        0 => 
        array (
          'folder' => false,
          'key' => '_3',
          'title' => 'The Simpsons',
          'data' => 
          array (
            'id' => '1',
            'parent_id' => '5',
          ),
        ),
        1 => 
        array (
          'folder' => false,
          'key' => '_4',
          'title' => 'Futurama',
          'data' => 
          array (
            'id' => '4',
            'parent_id' => '5',
          ),
        ),
      ),
    ),
    2 => 
    array (
      'folder' => true,
      'key' => '_5',
      'title' => 'Episodes',
      'data' => 
      array (
        'id' => '6',
        'parent_id' => '0',
      ),
      'children' => 
      array (
        0 => 
        array (
          'folder' => true,
          'key' => '_6',
          'title' => 'UK Episodes',
          'data' => 
          array (
            'id' => '7',
            'parent_id' => '6',
          ),
          'children' => 
          array (
            0 => 
            array (
              'folder' => false,
              'key' => '_7',
              'title' => 'Coupling',
              'data' => 
              array (
                'id' => '2',
                'parent_id' => '7',
              ),
            ),
          ),
        ),
        1 => 
        array (
          'folder' => true,
          'key' => '_8',
          'title' => 'AU Episodes',
          'data' => 
          array (
            'id' => '8',
            'parent_id' => '6',
          ),
        ),
      ),
    ),
  ),
)

I need to search through all sub arrays and build a new array returning the id and parent_id of each of the children AND also interpreting the order of the array children from the order they appear in the original array.

The output needs to end up something like this:

Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => 5
            [order] => 1
        )

    [1] => Array
        (
            [id] => 2
            [parent_id] => 7
            [order] => 1
        )

    [2] => Array
        (
            [id] => 4
            [parent_id] => 5
            [order] => 2
        )
)

I have tried the following recursion approach, however my code turns into a mess, and thats before I've even attempted to set the order of the items.

I've also searched stackoverflow for another example that I could learn from however I haven't found anything yet... If there is another example please feel free to point me in the right direction.

I appreciate any assistance!

Community
  • 1
  • 1
Tim
  • 3,091
  • 9
  • 48
  • 64

2 Answers2

1

A super easy way to run over all these is to use a RecursiveIteratorIterator over a RecursiveArrayIterator, pluck out the 'data' arrays and add in the key as the order.


Example:

$array = []; // Your starting array with stuff in it.

$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array),
    RecursiveIteratorIterator::SELF_FIRST
);
$result = [];
foreach ($iterator as $key => $value) {
    if (isset($value['data'])) {
        $result[] = array_merge($value['data'], ['order' => $key]);
    }
}

print_r($result);

Output:

Array
(
    [0] => Array
        (
            [id] => 3
            [parent_id] => 0
            [order] => 0
        )

    [1] => Array
        (
            [id] => 5
            [parent_id] => 0
            [order] => 1
        )

    [2] => Array
        (
            [id] => 1
            [parent_id] => 5
            [order] => 0
        )

    [3] => Array
        (
            [id] => 4
            [parent_id] => 5
            [order] => 1
        )

    [4] => Array
        (
            [id] => 6
            [parent_id] => 0
            [order] => 2
        )

    [5] => Array
        (
            [id] => 7
            [parent_id] => 6
            [order] => 0
        )

    [6] => Array
        (
            [id] => 2
            [parent_id] => 7
            [order] => 0
        )

    [7] => Array
        (
            [id] => 8
            [parent_id] => 6
            [order] => 1
        )

)
user3942918
  • 25,539
  • 11
  • 55
  • 67
  • Hi Paul, Wow this looks powerful and so far it looks like its working. Getting the order within the array is important as I need to send this to the DB. Using the value of `key` would be good enough, but I can't figure out how to add it into the result[] array... Any chance you could give me a clue? – Tim Oct 04 '14 at 11:05
  • I've tried adding `if ($key === 'key') { $result[$iterator]['order'] = $value; }` but it does not add anything in – Tim Oct 04 '14 at 11:16
  • Thanks, This is looking very good! I'm still testing but everything so far looks great. I can't tell you how much I appreciate it. Thanks – Tim Oct 04 '14 at 11:45
0

If i'm understanding what you're trying to do properly the below snippet should work. No need for the order key in each sub array because that's recorded automatically when you insert a new array index into $new_array.

Let me know if you have any other problems.

$new_array = [];

$current_array = []; //with all your data

foreach($current_array['children'] as $array) {
    $new_array[] = [
        'id' => $array['data']['id'],
        'parent_id' => $array['data']['parent_id'];
    ];
}
  • If not on PHP 5.4 or greater change short syntax for arrays to `array()` instead of `[]`. –  Oct 04 '14 at 08:04
  • Thanks for your answer Noah! Unfortunately your solution seems to be getting the top level children. With the test data above I'm only getting id's 3, 5 and 6 AKA "News", "Animations" and "Episodes". To clarify... I need to get the id's and children of all children, no matter how deep they are. And I really do need to return the order of each 'node' as I am inserting these values into a database... Does this make sense?? – Tim Oct 04 '14 at 08:43