0

Hi I have a flat array listed in the format below:

    id      parent  tag htmlcontent

    2-0     null    li  |home|
    1-0     2-0     ol  
    0-0     1-0     li  |about|
    6-0     null    li  |a|
    5-0     6-0     ol  
    4-0     5-0     li  |b|
    3-0     4-0     ol  
    2-1     3-0     li  |c|
    1-1     2-1     ol  
    0-1     1-1     li  |d|

I would like to build a recursive function to generate an unordered list eg..

<li>
  <ol>
   <li> home</li>
   <li> about </li>
  </ol>
...etc

How can I do this?

Edited by iamthwee

4
Contributors
14
Replies
74
Views
3 Years
Discussion Span
Last Post by albucurus
Featured Replies
  • 1
    diafol 3,669   3 Years Ago

    Erm, I don't think that's a great way of storing the data. You've gone for some type of 'adjacency list' method? I think I suggested 'nested sets' a while ago - although cheap reads, expensive writes. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ I think you'll find it easier inthe long run, but it takes a … Read More

  • 3
    diafol 3,669   3 Years Ago

    I undestood your table - just not sure if you need all the extras - ol/li - and the need for | around the labels. To explain the left and right values can be imagined as bus stop number as your finger traces its way around the drawn out hierarchy. … Read More

1

Erm, I don't think that's a great way of storing the data. You've gone for some type of 'adjacency list' method? I think I suggested 'nested sets' a while ago - although cheap reads, expensive writes.

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

I think you'll find it easier inthe long run, but it takes a little while to get your head around it. I posted an article on it before - but that was for binary trees - same sort of idea though. Here's an image of the model:

http://mikehillyer.com/media//numbered_tree.png

Edited by diafol

0

Hi, I don't understand the scheme, how it works the relation between id and parent?

The hypens are misleading, just consider it to be a unique id, as an example the about page has an id of 0-0 and its parent is the <ol> id 1-0.

You've gone for some type of 'adjacency list' method?

Not quite sure what you mean... it is a basic parent child relationship. I should be able to recurse through and build the list, but I need some help.

Full code would be appreciated.

Ta.

Edited by iamthwee

0

The array about should generate the list shown. 6923a6d4e44eb5a69adadcb82d86b684

In the diagram menu 'd' should come after menu 'c' I made a mistake with the attached picture.

The 'tag' is just for my reference telling me if it is a <li> or a <ol>

Edited by iamthwee

3

I undestood your table - just not sure if you need all the extras - ol/li - and the need for | around the labels.

To explain the left and right values can be imagined as bus stop number as your finger traces its way around the drawn out hierarchy. Something like this... (original image from the link in previous post)...

f1aa4a142804a16421f16f62c3d02ae0

And also from the same excellent resource:

We can retrieve the full tree through the use of a self-join that links parents with nodes on the basis that a node’s lft value will always appear between its parent’s lft and rgt values:

SELECT node.name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.name = 'ELECTRONICS'
ORDER BY node.lft;

Once again: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Edited by diafol

Votes + Comments
thanks but I'm not looking to change the structure
0

I can't change my db structure now diafol, plus I don't want to. It took ages to write a parser to extract the data from a complicated div. All I have is a flat array like the one above, I do agree some of the ols are unnecessary but that's just how the parser dumps it. I can NOT change this.

Just looking for a way to simply create a list from that data, complete code is what I'm after... using recursion.

Can anyone help... surely this must be easy.

0

I can't change my db structure now diafol, plus I don't want to

OK

Just looking for a way to simply create a list from that data, complete code is what I'm after... using recursion.

Heh heh - users asking for complete code usually get blasted. Spending a lot of time on something is not a reason to not use a better method, however, good luck with it, hope you get a solution :)

0

ok here is my attempt:

<?php 

 /**
  *  @Description: to build a recursive list from array
  *       @Params: array
  *
  *      @returns: list
  */

  // 2-0     null    li  |home|
  //   1-0     2-0     ol  
  //   0-0     1-0     li  |about|
  //   6-0     null    li  |a|
  //   5-0     6-0     ol  
  //   4-0     5-0     li  |b|
  //   3-0     4-0     ol  
  //   2-1     3-0     li  |c|
  //   1-1     2-1     ol  
  //   0-1     1-1     li  |d|


$arrayName[0] = array('id' => '2-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'home' );
$arrayName[1] = array('id' => '1-0', 'parent' => '2-0', 'tag' => 'ol', 'name' => '' );
$arrayName[2] = array('id' => '0-0', 'parent' => '1-0', 'tag' => 'li', 'name' => 'about' );
$arrayName[3] = array('id' => '6-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'a' );
$arrayName[4] = array('id' => '5-0', 'parent' => '6-0', 'tag' => 'ol', 'name' => '' );
$arrayName[5] = array('id' => '4-0', 'parent' => '5-0', 'tag' => 'li', 'name' => 'b' );
$arrayName[6] = array('id' => '3-0', 'parent' => '4-0', 'tag' => 'ol', 'name' => '' );
$arrayName[7] = array('id' => '2-1', 'parent' => '3-0', 'tag' => 'li', 'name' => 'c' );
$arrayName[8] = array('id' => '1-1', 'parent' => '2-1', 'tag' => 'ol', 'name' => '' );
$arrayName[9] = array('id' => '0-1', 'parent' => '1-1', 'tag' => 'li', 'name' => 'd' );



 for ($i=0; $i < 9 ; $i++) 
 {

    echo $arrayName[$i]['id'];
    echo " ". $arrayName[$i]['parent'];
    echo " ". $arrayName[$i]['tag'];
    echo " ". $arrayName[$i]['name'];
    echo ('<br/>');
 }

  /**
   *  @Description: recursive function to build list
   *       @Params: --
   *
   *     @returns: --
   */

function buildNavigation($items, $parent = "null")
{
    $hasChildren = false;
    $outputHtml = '<ul>%s</ul>';
    $childrenHtml = '';

    foreach($items as $item)
    {
        if ($item['parent'] == $parent) {
            $hasChildren = true;
            $childrenHtml .= '<li>'.$item['name'];         
            $childrenHtml .= buildNavigation($items, $item['id']);         
            $childrenHtml .= '</li>';           
        }
    }

    // Without children, we do not need the <ul> tag.
    if (!$hasChildren) {
        $outputHtml = '';
    }

    // Returns the HTML
    return sprintf($outputHtml, $childrenHtml);
}

print buildNavigation($arrayName);



 ?>

it is working but giving me extra uls

<ul>
    <li>home
        <ul>
            <li>
                <ul>
                    <li>about</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>a
        <ul>
            <li>
                <ul>
                    <li>b
                        <ul>
                            <li>
                                <ul>
                                    <li>c
                                        <ul>
                                            <li>
                                                <ul>
                                                    <li>d</li>
                                                </ul>
                                            </li>
                                        </ul>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>
0

I need to somehow reduce my array to :

$arrayName[0] = array('id' => '2-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'home' );
$arrayName[1] = array('id' => '0-0', 'parent' => '2-0', 'tag' => 'li', 'name' => 'about' );
$arrayName[2] = array('id' => '6-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'a' );
$arrayName[3] = array('id' => '4-0', 'parent' => '6-0', 'tag' => 'li', 'name' => 'b' );
$arrayName[4] = array('id' => '2-1', 'parent' => '4-0', 'tag' => 'li', 'name' => 'c' );
$arrayName[5] = array('id' => '0-1', 'parent' => '2-1', 'tag' => 'li', 'name' => 'd' );

i.e get rid of the uls but shift up the parent child relationship.

0

not pretty but:

<?php 

 /**
  *  @Description: to build a recursive list from array
  *       @Params: array
  *
  *      @returns: list
  */

  // 2-0     null    li  |home|
  //   1-0     2-0     ol  
  //   0-0     1-0     li  |about|
  //   6-0     null    li  |a|
  //   5-0     6-0     ol  
  //   4-0     5-0     li  |b|
  //   3-0     4-0     ol  
  //   2-1     3-0     li  |c|
  //   1-1     2-1     ol  
  //   0-1     1-1     li  |d|


$arrayName[0] = array('id' => '2-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'home' );
$arrayName[1] = array('id' => '1-0', 'parent' => '2-0', 'tag' => 'ol', 'name' => 'kkkkkkkk' );
$arrayName[2] = array('id' => '0-0', 'parent' => '1-0', 'tag' => 'li', 'name' => 'about' );
$arrayName[3] = array('id' => '6-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'a' );
$arrayName[4] = array('id' => '5-0', 'parent' => '6-0', 'tag' => 'ol', 'name' => '' );
$arrayName[5] = array('id' => '4-0', 'parent' => '5-0', 'tag' => 'li', 'name' => 'b' );
$arrayName[6] = array('id' => '3-0', 'parent' => '4-0', 'tag' => 'ol', 'name' => '' );
$arrayName[7] = array('id' => '2-1', 'parent' => '3-0', 'tag' => 'li', 'name' => 'c' );
$arrayName[8] = array('id' => '1-1', 'parent' => '2-1', 'tag' => 'ol', 'name' => '' );
$arrayName[9] = array('id' => '0-1', 'parent' => '1-1', 'tag' => 'li', 'name' => 'd' );


 /**
  *  @Description: cleans  the array removing ul tags and shifting 
  *                the parent child relationship.
  *                1.loop through select parent  -> id 
  *                2. Check if  tag is ol
  *                3. If it is change original parent to id
  *                4. Remove ul array (not sure if this is necessary)
  *       @Params: params
  *
  *     @returns: returns
  */

 clean_array($arrayName);

 function clean_array($arrayName)
 {

    for ($i=0; $i < count($arrayName); $i++) { 

      if (is_parent_ol($arrayName[$i]['parent'],$arrayName))  
      {
         //$arrayName[$i]['parent'] =
          $tmp =get_new_parent($arrayName[$i]['parent'],$arrayName);
          $arrayName[$i]['parent'] = $tmp;
        echo ('<br/>');
      }
      else
      {
        //do nothing!!
      }


    }

    hai($arrayName);
 }

 function is_parent_ol($id,$arrayName)
 {
  //echo $id;
    $my_counter = 0;
    for ($i=0; $i < count($arrayName); $i++) { 
      if($arrayName[$i]['id']==$id)
      {
        if($arrayName[$i]['tag'] == "ol")
        {
          //echo 'foo';
          $my_counter++;
        }
      }
    }
    if ($my_counter > 0)
    {
      return true;
    }
    else{
      return false;
    }
 }

 function get_new_parent($id,$arrayName)
 {

  //echo "*".$id."*";
   for ($i=0; $i < count($arrayName); $i++) { 
    //echo "%".$arrayName[$i]['id'];
      if($arrayName[$i]['id']===$id)
      { echo "*" .$arrayName[$i]['parent'];

        return $arrayName[$i]['parent'];
         }
    }

 }

function hai($arrayName){
 $kk    =count($arrayName);
 for ($i=0; $i <$kk;$i++)
 {
    if($arrayName[$i]['tag']=='ol')
    {
      unset($arrayName[$i]);
    }

 }



 // echo $arrayName[$i]['id'];
 //    echo " ". $arrayName[$i]['parent'];
 //    echo " ". $arrayName[$i]['tag'];
 //    echo " ". $arrayName[$i]['name'];
 //    echo ('<br/>');

print buildNavigation($arrayName,$parent="null");
}

  /**
   *  @Description: recursive function to build list
   *       @Params: --
   *
   *     @returns: --
   */

function buildNavigation($items, $parent = "null")
{
    $hasChildren = false;
    $outputHtml = '<ul>%s</ul>';
    $childrenHtml = '';

    foreach($items as $item)
    {
        if ($item['parent'] == $parent) {
            $hasChildren = true;
            $childrenHtml .= '<li>'.$item['name'];         
            $childrenHtml .= buildNavigation($items, $item['id']);         
            $childrenHtml .= '</li>';           
        }
    }

    // Without children, we do not need the <ul> tag.
    if (!$hasChildren) {
        $outputHtml = '';
    }

    // Returns the HTML
    return sprintf($outputHtml, $childrenHtml);
}

//print buildNavigation($arrayName);












 ?>
0

No this is turning into a nightmare my parser is wrong, I'm going have to revisit this.

0

Hi,
Try this please !

<?php
    $arrayName[0] = array('id' => '2-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'home' );
    $arrayName[1] = array('id' => '1-0', 'parent' => '2-0', 'tag' => 'ol', 'name' => '' );
    $arrayName[2] = array('id' => '0-0', 'parent' => '1-0', 'tag' => 'li', 'name' => 'about' );
    $arrayName[3] = array('id' => '6-0', 'parent' => 'null', 'tag' => 'li', 'name' => 'a' );
    $arrayName[4] = array('id' => '5-0', 'parent' => '6-0', 'tag' => 'ol', 'name' => '' );
    $arrayName[5] = array('id' => '4-0', 'parent' => '5-0', 'tag' => 'li', 'name' => 'b' );
    $arrayName[6] = array('id' => '3-0', 'parent' => '4-0', 'tag' => 'ol', 'name' => '' );
    $arrayName[7] = array('id' => '2-1', 'parent' => '3-0', 'tag' => 'li', 'name' => 'c' );
    $arrayName[8] = array('id' => '1-1', 'parent' => '2-1', 'tag' => 'ol', 'name' => '' );
    $arrayName[9] = array('id' => '0-1', 'parent' => '1-1', 'tag' => 'li', 'name' => 'd' );


/**
* @Description: recursive function to build list
* @Params: --
*
* @returns: --
*/
    function buildNavigation($items, $parent = "null")
    {
        $hasChildren = false;
        $outputHtml = '<ul>%s</ul>'; 
        $childrenHtml = '';
        foreach($items as $item)
        {
            if ($item['parent'] == $parent) 
            {
                $hasChildren = true;
                if($item['name'] != '')
                {
                    $childrenHtml .= '<li>'.$item['name'];
                    $childrenHtml .= '</li>';
                }
                $childrenHtml .= buildNavigation($items, $item['id']); 
            }            
        }
        // Without children, we do not need the <ul> tag.
        if (!$hasChildren) 
        {
            $outputHtml = '';
        }

        // Returns the HTML
        return sprintf($outputHtml, $childrenHtml);
    }



print buildNavigation($arrayName);

?>
This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.