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
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

 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.");
    }

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.