Jump to content

Converting an array to a tree structure


Roaziel

Recommended Posts

Ok, so let's say I have a file called houses.txt and it contains the following

 

family1.dad=frank
family1.mom=Julie
family1.son=Billy
family1.daughter.toy=barbie
family1.daughter.boyfriend=Sam
family2=bachelor
family3.roommate1=Joel
family3.roommate2=Hank

 

I want to be able to take that file and make a tree structure that looks like this

 

array(3) {
  ["family1"]=>
  array(4) {
    ["dad"]=> "frank"
    ["mom"]=> "Julie"
    ["son"]=> "Billy"
    ["daughter"]=>    
    array(2) {
["toy"]=>  "barbie"
["boyfriend"]=> "Sam"
    }    
  }
  ["family2"]=> "bachelor"
  ["family3"]=>    
  array(2) {
    ["roommate1"]=> "Joel"
    ["roommate2"]=>  "Hank"
  }     
}

 

 

Now what I've done so far is I've opened the file with file(), then looped the file variable and for ever line I just explode where theres a = and then I explode the first entry (0) of the previous explode result with the dot character.

 

But this is where I freeze, I'm totally stumped. Where do I go from here??

 

Please, anyone?

Link to comment
https://forums.phpfreaks.com/topic/193920-converting-an-array-to-a-tree-structure/
Share on other sites

I'm not sure I follow what you are looking to do!

 

What are you planning to do with the information after you build your array?

 

 

Why NOT convert you data into XML Format?  It will allow you to tag and build a tree-like structure.

 

When viewed with an XML viewer (or your browser) it will display as a TREE Structure...

 

PHP5 has support for a nifty little function called SimpleXML...  Take a look, this may help you accomplish what you are trying to do...

 

 

http://www.phpro.org/tutorials/Introduction-To-SimpleXML-With-PHP.html    *** really good tutorial ***

 

http://www.w3schools.com/php/php_xml_simplexml.asp

 

http://php.net/manual/en/book.simplexml.php

 

 

I would loop and explode on the dot into an array then pop off the bottom and explode on the = then play with count and loop or extract to build an associative array.

 

 

HTH

Teamatomic

 

umm, not a good idea since what comes after = can also have dots. But either way that's not the problem. I've already so far that I have an array of the titles for a line (like array("family1", "daughter", "toy"); ) since I looped the file() variable, but that's where I get stuck, how do I now stack them up as a tree and add the result (what came after the = ) to the end of the specific line?

 

This is kicking my ass, so I seriously hope someone out there's got a seriously powerful brain an can tackle this.

Like this?

Array
(
    [family1] => Array
        (
            [dad] => frank

            [mom] => Julie

            [son] => Billy

            [daughter] => Array
                (
                    [toy] => barbie

                    [boyfriend] => Sam

                )

        )

    [family2] => bachelor

    [family3] => Array
        (
            [roommate1] => Joel

            [roommate2] => Hank
        )

)

 

 

HTH

Teamatomic

Like this?

Array
(
    [family1] => Array
        (
            [dad] => frank

            [mom] => Julie

            [son] => Billy

            [daughter] => Array
                (
                    [toy] => barbie

                    [boyfriend] => Sam

                )

        )

    [family2] => bachelor

    [family3] => Array
        (
            [roommate1] => Joel

            [roommate2] => Hank
        )

)

 

 

HTH

Teamatomic

 

uhh, yeah I already showed the structure in my original post.

Then I dont understand what you need if you have already done the example into the array I pasted.

 

 

HTH

Teamatomic

 

Lol, no I need a function that returns an array structure like that. The function gets fed a file path, I opened the file path and did all that other stuff I already mentioned but now I need to actually use what I done so far to make the function build a structure like that and then return it.

Thats what I did, except monolith style, not a function. I then pasted the resulting array to ask you if it was in fact what you were looking for. Seeing as it is this is what you need to do.

$array=array()

foreach(lines as line)

you need to explode each line on the dot

count the array

if its one, do this

list($key,$value)=explode("=",$Bline[0]);
$array[$key]=$value;

the rest are an expanded version of the above. Seeing as its a class exercise its up to you now.

hint:

family1.daughter.toy=barbie==key1.key2.key3=value

 

You had the right idea but were working backwards.

 

 

HTH

Teamatomic

That looks great, but one problem however, the value after = can have several dots, so if I explode the dot first it'll explode the result.

 

Edit: come to think of it, lots of things you mentioned don't make sense.. For starters, what's $Bline? assuming it's the result of the dot explosion then there might not be a = in there at all if it has more subcategories.

Array
(
    [family1] => Array
        (
            [son] => "bob.john.dan"
        )
)

 

 

P.S. I really don't understand what you mean by "family1.daughter.toy=barbie==key1.key2.key3=value", one line might look like that bu another may only have one main array, like family2. And I already know what the structure looks like I just don't know how to stack them into the tree as suggested.

This is what I've got so far.

 

if(is_readable($file_path)){
        if($settings = file($file_path)){
            $arrSettings = array();
            
            foreach($settings as $settingLn){
                $arrSettingLn = array();
                
                $arrData = explode("=", $settingLn);
                $arrSettingNames = explode(".", $arrData[0]);
                
                for($x = (count($arrSettingNames) - 1); $x => 0; $x--){
                    if($x == (count($arrSettingNames) - 1)){
                        $settingTitle[] = array($arrSettingNames[$x] => $arrData[1]);
                    }else{
                        
                    }
                }
                
                $arrSettings[] = $arrSettingLn;
            }
        }else{
            return array("error2" => "File could not be read.");
        }
    }else{
        return array("error1" => "File is not readable or doesn't exist.");
    }

Not my way of doing it. But thats PHP. Many ways to accomplish the same thing

foreach(lines as line)

list($key,$value)=explode("=",$line);

now you have the value and the keys

keys=explode(".",key)

kc=count(keys)

key1=keys[0];

key2=keys[1];

etc.

then work on the key count

if (kc==1)$array[$key1]=$value;

if(kc==2)$array[$key[1][$key2]=$value

etc

 

 

 

HTH

Teamatomic

Yeah, I've com this far now:

 

<?php
if(is_readable($file_path)){
        if($settings = file($file_path)){
            $arrSettings = array();
            
            foreach($settings as $settingLn){
                $arrSettingLn = array();
                
                list($keys, $value) = explode("=", $settingLn);
                $arrSettingNames = explode(".", $keys);
                
                for($x = (count($arrSettingNames) - 1); $x => 0; $x--){
                    if($x == (count($arrSettingNames) - 1)){
                        $arrSettingLn = array($arrSettingNames[$x] => $value);
                    }else{
                        $arrSettingLn = array($arrSettingNames[$x] => $settingTitle;
                    }
                }
            }
            
            
        }else{
            return array("error2" => "File could not be read.");
        }
    }else{
        return array("error1" => "File is not readable or doesn't exist.");
    }

?>

 

Which means I have the lines fully structured, but now I need to merge them into one array. Problem is array_merge() replaces existing key values. So there would only be one family1 entry and it would be the last one since that's the last one entered and it would overwrite the existing ones.

Ok, I've made quite some progress, but now I'm unfortunately stuck again.

 

Here is what the code looks like at the moment.

 

<?php
if(is_readable($file_path)){
        if($settings = file($file_path)){
            $arrSettings = array();
            
            foreach($settings as $settingLn){
                $settingLn = str_replace("\n", "", $settingLn);
                $arrSettingLn = array();
                
                list($keys, $value) = explode("=", $settingLn);
                $arrSettingNames = explode(".", $keys);
                
                for($x = (count($arrSettingNames)-1); $x >= 0; $x--){
                    if($x == (count($arrSettingNames) - 1)){
                        $arrSettingLn = array($arrSettingNames[$x] => $value);
                    }else{
                        $arrSettingLn = array($arrSettingNames[$x] => $settingTitle);
                    }
                }
                
                $arrSettings = array_merge_recursive($arrSettings, $arrSettingLn);
            }
            
            return $arrSettings;
        }else{
            return array("error2" => "File could not be read.");
        }
    }else{
        return array("error1" => "File is not readable or doesn't exist.");
    }
?>

 

And this is what it's producing:  http://people.dsv.su.se/~gora-mak/uppgift3.php

 

As you can see something is wrong. The first layer seems to work just fine, I see family1, family2 and family3, but only family 2 is showing it's content, the other two get NULL. Strange how it happens to these when these are the only ones that have sub-array.

 

Anyone have any idea why it is doing this and how I'd fix it? My theory is that the function simply isn't affecting the inner array so if they clash they become NULL for some reason... don't ask me why.... Any suggestions?

Archived

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

×
×
  • Create New...

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.