Jump to content

Archived

This topic is now archived and is closed to further replies.

Staggan

Script to display array as a tree

Recommended Posts

Hello

 

I have an array that I would like to display as a family tree... and am looking for an example script that will allow me to do this.

 

I want to be able to create X number of generations and fill the boxes with data from my array....

 

So, if I want 5 generations I want to generate a tree with 63 elements or boxes

 

Any help would be appreciated

 

Thanks

 

Share this post


Link to post
Share on other sites

What is the format of the array and how do you want the output to look?

Share this post


Link to post
Share on other sites

Here is a small script that will create a table in the general format of a family tree based upon the number of generations given. But, I would need to know the format of your input array to know how to populate the contents.

 

<?php

$generations = 5;

$total_columns = pow(2, $generations);
$familyTree = '';

for($gen = 0; $gen <= $generations; $gen++)
{
    $gen_family_count = pow(2, $gen);

    $colspan = $total_columns / $gen_family_count;

    $familyTree .= "<tr>\n";
    for($i=0; $i<$gen_family_count; $i++)
    {
        $familyTree .= "<td colspan='{$colspan}'>{$i}</td>\n";
    }
    $familyTree .= "<tr>\n";
}

?>
<html>
<head>
  <style>
    td { text-align: center; }
  </style>
</head>
<body>

<table border='1'>
    <?php echo $familyTree; ?>
</table>

</body>
</html>

Share this post


Link to post
Share on other sites

Hello

 

My array is formatted as follows:

 

0 first level

2, 1 second level

6, 5, 4, 3 third level

 

and so on, populating from right to left

 

Here is a complete example of the array:

 



Array
(
    [0] => Kegluneq Aaliyah
    [1] => Arctictreks Dark As Night
    [2] => Arctictrek Silver Spirit
    [3] => KEBUCK SCHRIMSHANDER
    [4] => ARCTICTREKS CHERISH FOREVER
    [7] => Pat Gagnon
    [8] => Coquette La Rouge D'Ericlam
    [15] => Ewok D'Ericlam
    [16] => Heidi D'Ericlam
    [31] => David Le Noir D'Ericlam
    [32] => B-Wouack De Patcie
    [33] => Comanche D'Ericlam
    [34] => Finskan D'Ericlam
    [17] => Himmuk D'Ericlam
    [18] => Inouska D'Ericlam
    [35] => Comanche D'Ericlam
    [36] => Finskan D'Ericlam
    [37] => Diable Le Rouge D'Ericlam
    [38] => Frosty D'Ericlam
    [9] => Storm Kloud's Chosen to Win
    [10] => Arctictrek's Indiana
    [19] => Storm Kloud's Keep the Win
    [20] => Storm Kloud's Hharmony
    [39] => Storm Kloud's Oomiak
    [40] => Storm Kloud Ddawn In The North
    [41] => Storm Kloud's Better Than Ever
    [42] => Princess Nikkita Sno-Kloud
    [21] => Jacbar Alaskan Black Night
    [22] => Rameslyn Cherokee Squaw
    [43] => Highnoons Kaskinampo of Jacbar
    [44] => Malnorska's Gypsy Lady
    [45] => Fire 'N Ice In Conclusion
    [46] => Highnoons Loucheuse
    [5] => Shepherdsway Touch of Gold
    [6] => Arctictreks Legend of a Lady
    [11] => Outriggers Red Wolf
    [12] => Eastern Hill Coldfoot Coco
    [23] => Keikewabic's P'Tis Guy
    [24] => Keikewabic's Chitina
    [47] => Keikewabic's P'Tis N'Ours
    [48] => Keikewabic's Mitchie
    [49] => Keikewabic's P'Tis N'Ours
    [50] => Keikewabic & Burley's Merlin
    [25] => Yukon (N5)
    [26] => Ivalos Ayla
    [51] => A-Mikko
    [52] => B Ika Tanana
    [53] => Ivalos Froststar
    [54] => Chinooks Ivalo
    [13] => Shepherdsway Phantom Scout
    [14] => Arctictrek's Indiana
    [27] => Storm Kloud's Chosen to Win
    [28] => Shepherdsway Black Oasis
    [55] => Storm Kloud's Keep the Win
    [56] => Storm Kloud's Hharmony
    [57] => Fire 'N Ice In Conclusion
    [58] => Highnoons Ottawa
    [29] => Jacbar Alaskan Black Night
    [30] => Rameslyn Cherokee Squaw
    [59] => Highnoons Kaskinampo of Jacbar
    [60] => Malnorska's Gypsy Lady
    [61] => Fire 'N Ice In Conclusion
    [62] => Highnoons Loucheuse
)

 

I already know the number of generations because I set that at the beginning

 

Thanks

 

Share this post


Link to post
Share on other sites

Is there any reason why the keys are out of order?

Share this post


Link to post
Share on other sites

It seems to be the way my recursive function returns the indexes....

 

I can reorder it if need be....

 

 

 

Share this post


Link to post
Share on other sites

OK, so, I have it working.... thank you... but some more advice if you could...

 

here is the changed code:

 


$generations = $numLevelsToSearch;
$elements = 0 ;

$total_columns = pow(2, $generations);

$familyTree = '';

for($gen = 0; $gen <= $generations; $gen++){    

	$gen_family_count = pow(2, $gen);    
	$colspan = $total_columns / $gen_family_count;    
	$familyTree .= "<tr>\n";    

	for($i=0; $i<$gen_family_count; $i++){        
	$elements +=1;
	$familyTree .= "<td colspan='{$colspan}'>{$familyTreeArray[$elements]}</td>\n";    
	}    

	$familyTree .= "<tr>\n";}
	echo $elements;
?>


	<html><head>  <style>    td { text-align: center; }  </style></head><body><table border='1'>    <?php echo $familyTree; ?></table></body></html>

<?  


 

How can I increase the spacing and is it possible to also do this horizontally?

 

Thanks

 

 

Share this post


Link to post
Share on other sites

Actually, it is not quite right....

 

not sure what is wrong though.... think the positions are off a little.

Share this post


Link to post
Share on other sites

Fixed that...

 

I was adding to $elements in the loop before displaying it.. moved it to after and it works now...

 

 

Share this post


Link to post
Share on other sites

It really depends.

 

foreach will loop through the arrays in whatever order they're already in

for will loop through the keys in numerical order.

 

<?php

$family = range(0,62);
$familySize = count( $family );

// This will determine how many columns will be in our biggest branch
// http://en.wikipedia.org/wiki/Power_of_two#Algorithm_to_convert_any_number_into_nearest_power_of_two_number
$colspan = pow(2,ceil(log($familySize/2,2)));
$x = 1; $y = 1;
echo '<table border="1">';
foreach( $family as $member ) {

if( $x == 1 ) echo '<tr>';

echo '<td colspan="'.$colspan.'">'.$member.'</td>';

if( $x == pow(2,$y-1) ) {
	echo '</tr>';
	$colspan /= 2;
	$y++; $x = 1;
} else $x++;

}
echo '</table>';

?>

 

Keep in mind, the code won't create blank cells if the data doesn't 'fit' perfectly into the tree.

Share this post


Link to post
Share on other sites

Hi...

 

It all works, thanks.

 

I don't have empty elements I fill them with "No Details" so it still gives the complete pedigree.

 

I would still like to know if I can display this from left to right as an option though, is that possible?

 

Thanks

Share this post


Link to post
Share on other sites

Of course it is. You'd have to show us how you want it displayed though.

Share this post


Link to post
Share on other sites

Thanks...

 

 

            3

        1

            4

0

            5     

        2

            6

 

 

I hope that makes sense ?

 

Thanks again

Share this post


Link to post
Share on other sites

Of course, you're going to have to do different calculations though. Here's a helpful graph

 

0  1  3  7  15 31
               32
            16 33
               34
         8  17 35
               36
            18 37
               38
      4  9  19 39
               40
            20 41
               42
         10 21 43
               44
            22 45
               46
   2  5  11 23 47
               48
            24 49
               50
         12 25 51
               52
            26 53
               54
      6  13 27 55
               56
            28 57
               58
         14 29 59
               60
            30 61
               62

 

You need to turn that into a table, using rowspan.

Share this post


Link to post
Share on other sites

Yeah, that is going to be much more complicated as you will need to build the rows in a more complex format. Not impossible, but will take some analytical and mathematical skills.

Share this post


Link to post
Share on other sites

Not getting very far, heh.

 

I understand my first rowspan should be = to the number of rows I'll need.

 

Which for a 3 generation pedigree is 8 rows... so my first row span should be 8 rows with a single value

 

my second should be 2 entries, each spanning 4 rows

 

my third should be 4 entries each spanning 2 rows

 

and my last 8 entries each spannnig a single row...

 

But I am not sure how to build this table, let alone populate it yet....

 

I am sure I am being stupid but not sure why... everything I have tried so far just gives me some wierd layout....

 

 

 

 

Share this post


Link to post
Share on other sites

Ok, here you go. I'm not even going to try and explain the logic

<?php

$generations = 3;

//Create temp array to store results
$genTableArray = array();
for($genCol = 0; $genCol <= $generations; $genCol++)
{
    $genRowCount = pow(2, $genCol);
    $rowspan = pow(2, $generations) / $genRowCount;

    for($familyGenCount=0; $familyGenCount<$genRowCount; $familyGenCount++)
    {
        $personIndex = pow(2, $genCol) + $familyGenCount - 1;
        $rowIndex = $rowspan * $familyGenCount;
        $genTableArray[$rowIndex][] = "<td rowspan='{$rowspan}'>$personIndex - {$familyTreeArray[$personIndex]}</td>\n";
    }
}

//Output the array into a table
ksort($genTableArray);
$familyTreeHTML = '';
foreach($genTableArray as $rowData)
{
    $familyTreeHTML .= "<tr>\n" . implode("\n", $rowData) . "</tr>\n";
}

?>
<html>
<head>
  <style>
    td { text-align: center; }
  </style>
</head>
<body>

<table border='1'>
    <?php echo $familyTreeHTML; ?>
</table>

</body>
</html>

 

I tried to write it to create the table directly, but couldn't figure out the formulas to determine which records to output on each row. So, I just processed the records similar to the original scripts but then dynamically populate an array.

Share this post


Link to post
Share on other sites

Thank you for your help....

 

I'll spend some time going over this to understand it....

 

Thanks again....

Share this post


Link to post
Share on other sites

I'll spend some time going over this to understand it....

 

Good luck. I barely understand it myself (LOL). Actually, I understood each part as I did it, but didn't comment as I went. Some of it is kind of abstract.

Share this post


Link to post
Share on other sites

OK, here is the code with more comments

$generations = 5;

//Create temp array to store results
$genTableArray = array();
//Run through each column based upon the number of generations.
//The column count is generation + 1
for($genCol = 0; $genCol <= $generations; $genCol++)
{
    //Detemine the number of rows/records in the colum (1, 2, 4, 8, 16, ...)
    $genRowCount = pow(2, $genCol);
    //Detemine the rowspan for each record/row in this column
    //This will be the (total # rows / record in this row)
    //The total # of rows is based upon the number of generations to the power of 2
    $rowspan = pow(2, $generations) / $genRowCount;

    //Run a loop for the number of records in this column
    for($familyGenCount=0; $familyGenCount<$genRowCount; $familyGenCount++)
    {
        //Calculate the person index to use based upon the column / row
        //First column has index 0, second column has 1/2, third column has 3/4/5/6, etc.
        //The formula is needed due to the size being dynamic
        $personIndex = pow(2, $genCol) + $familyGenCount - 1;
        //Determine the row index for this record. This is dynamic based upon the 
        //total number of columns and the column/record beign displayed. For example,
        //if there are 3 generation there will be a total of 8 rows. Column 2 will have two records
        //So record 1 will go in the first row and record 2 will go into the 4th row
        $rowIndex = $rowspan * $familyGenCount;
        //Add the recod to the appropriate (row) in the array using the rowspan. The key of the array is the row index
        $genTableArray[$rowIndex][] = "<td rowspan='{$rowspan}'>$personIndex - {$familyTreeArray[$personIndex]}</td>\n";
    }
}

//Output the array into a table
//Since records weren't added to rows in order (0, 1, 2, ...) need to sort
//the array by keys to get int he correct order
ksort($genTableArray);
$familyTreeHTML = '';
//Loop through each row in order and implode the values into an output variable
foreach($genTableArray as $rowData)
{
    $familyTreeHTML .= "<tr>\n" . implode("\n", $rowData) . "</tr>\n";
}

 

Also, so you can understand the final process, here is what the temp array looks like before the final processing

Array
(
    [0] => Array
        (
            [0] => <td rowspan='8'>0 - Kegluneq Aaliyah</td>
            [1] => <td rowspan='4'>1 - Arctictreks Dark As Night</td>
            [2] => <td rowspan='2'>3 - KEBUCK SCHRIMSHANDER</td>
            [3] => <td rowspan='1'>7 - Pat Gagnon</td>
        )

    [1] => Array
        (
            [0] => <td rowspan='1'>8 - Coquette La Rouge D'Ericlam</td>
        )

    [2] => Array
        (
            [0] => <td rowspan='2'>4 - ARCTICTREKS CHERISH FOREVER</td>
            [1] => <td rowspan='1'>9 - Storm Kloud's Chosen to Win</td>
        )

    [3] => Array
        (
            [0] => <td rowspan='1'>10 - Arctictrek's Indiana</td>
        )

    [4] => Array
        (
            [0] => <td rowspan='4'>2 - Arctictrek Silver Spirit</td>
            [1] => <td rowspan='2'>5 - Shepherdsway Touch of Gold</td>
            [2] => <td rowspan='1'>11 - Outriggers Red Wolf</td>
        )

    [5] => Array
        (
            [0] => <td rowspan='1'>12 - Eastern Hill Coldfoot Coco</td>
        )

    [6] => Array
        (
            [0] => <td rowspan='2'>6 - Arctictreks Legend of a Lady</td>
            [1] => <td rowspan='1'>13 - Shepherdsway Phantom Scout</td>
        )

    [7] => Array
        (
            [0] => <td rowspan='1'>14 - Arctictrek's Indiana</td>
        )
)

Share this post


Link to post
Share on other sites

Thanks.... it will help me to understand it much more easily.

 

I am probably taking advantage, but am I able to add an onclick into the population of the table?

 

For example, if I generated the table, and then wanted to click on one of the dogs to bring up a new table in a new page with that dog as the root... is that possible?

 

Can I call a function on click to post to a new page?

 

Thanks

 

 

Share this post


Link to post
Share on other sites

<style type="text/css">
<!--
div.tree {
   text-align: center;
   float: right;
}
div.clr {
   clear: both;
}
//-->
</script>

echo '<div>';

sort($tree, SORT_NUMERIC);
$i = 1;
$n = count($tree)-1;
for($lvl = 0; $lvl < $n; ++$lvl)
{
   $decendant = isset($tree[$lvl]) ? stripslashes(htmlentities($tree[$lvl], ENT_QUOTES, 'UTF-8')) : 'Unknown';
   echo '<div class="tree" style="width: '. (100/pow(2, $i-1)) .'%;">'. $decendant .'</div>';
   if ( (pow(2, $i-1) % $lvl) == 0 )
   {
      echo '<div class="clr"></div>';
      $i++;
   }
}
echo '</div>';

That work?

Share this post


Link to post
Share on other sites

The previous poster, Mjdamato gave me a working solution that works fine... thanks.

 

This will allow me to understand how to do it so I can extend it for the functionality I am looking for...

Share this post


Link to post
Share on other sites

Can I call a function on click to post to a new page?

 

There is only one line in that code that produces the actual output

$genTableArray[$rowIndex][] = "<td rowspan='{$rowspan}'>$personIndex - {$familyTreeArray[$personIndex]}</td>\n"

 

Put whatever other content you want in that. In this case, either put an onclick inside the TD tag or change teh content in the TD tags to a hyperlink. At the very least though, you would need to pass a value so the next page knows what dog to create the results on next. I guess you could use the name, but you should be passing an id value. But, your array doesn't contain an id, so . . .

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.