phil
phil

Reputation: 157

Convert multidimensional array to nested set array

im having a little problem i need some help with. Im trying to convert a multidimensional array into a flatten array with nested set values right and left like so:

    $array = {
         'id' => 1
         'name' => 'john'
         'childs' => array(
             array(
                 'id' => 1
                 'name' => 'jane'
             )
          )        
    }

to

    $array = {
         array(
           'id' => 1,
           'name' => 'john'
           'left' => '1'
           'right' => '4'
         ),
         array(
           'id' => 1,
           'name' => 'jane'
           'left' => '2'
           'right' => '3'
         )
    }

Any help is appreciated!

Upvotes: 1

Views: 1084

Answers (3)

Gordon Freeman
Gordon Freeman

Reputation: 3421

For anyone coming here and looking for a solution, loneTraceur's solution works fine. However, I needed one in OOP, so here is my version of it.

<?php

class NestedSet
{
    protected $tree = [];

    public function deconstruct($tree, $left = 0)
    {
        $this->flattenTree($tree, $left);
        return $this->tree;
    }

    protected function flattenTree($tree, $left)
    {
        $indexed = [];
        $indexed['id'] = $tree['id'];
        $indexed['_lft'] = $left + 1;

        $right = $indexed['_lft'];

        if (isset($tree['children']) && count($tree['children'])) {
            foreach ($tree['children'] as $child) {
                $right = $this->flattenTree($child, $right);
            }
        }

        $indexed['_rgt'] = $right + 1;

        $this->tree[] = $indexed;

        return $indexed['_rgt'];
    }
}

You would run it like this:

$NestedSet = new NestedSet;
$flat = $NestedSet->deconstruct($tree):

This code is based on the other answer.

Upvotes: 1

loneTraceur
loneTraceur

Reputation: 100

I asked a very similar question and got a result, so thought I'd send it on for you. I realise this is quite an old topic, but still worth getting an answer. I've included my data, but would be easily adapted for yours.

$JSON = '[{"id":1,"children":[{"id":2,"children":[{"id":3},{"id":4}]},{"id":5}]}]';
$cleanJSON = json_decode($JSON,true);

$a_newTree = array();       

function recurseTree($structure,$previousLeft) 
{
    global $a_newTree;  // Get global Variable to store results in.

    $indexed = array();                     // Bucket of results.       
    $indexed['id'] = $structure['id'];      // Set ID
    $indexed['left'] = $previousLeft + 1;   // Set Left

    $lastRight = $indexed['left'];

    $i_count = 0;
    if ($structure['children'])
    {
        foreach ($structure['children'] as $a_child)
        {
            $lastRight = recurseTree($structure['children'][$i_count],$lastRight);
            $i_count++;
        }
    }

    $indexed['right'] = $lastRight + 1;     // Set Right

    array_push($a_newTree,$indexed);        // Push onto stack

    return $indexed['right'];       
}

recurseTree($cleanJSON[0],0);
print_r($a_newTree);

Upvotes: 2

Electronick
Electronick

Reputation: 1122

function restructRecursive($array, $left = 1) {
  if (isset($array['childs'])) {
    $result = array();
    foreach ($array['childs'] as $child) {
      $result = array_merge($result, restructRecursive($child, $left+1));
    }
    unset($array['childs']);
  }
  $array['left'] = $left;
  return array_merge(array($array), $result);
}

$newStruct = restructRecursive($oldStruct);

Upvotes: 1

Related Questions