Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8153839
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T16:09:02+00:00 2026-06-06T16:09:02+00:00

I would like convert the below text into a nested array, something like you

  • 0

I would like convert the below text into a nested array, something like you would get with MPTT database structure.

I am getting the data from a shell script and need to display it on a website. Don’t have any control over the format :/

There is lots of information about array -> list, but not much going the other way.

Any input would be appreciated, thanks.

cat, true cat
       => domestic cat, house cat, Felis domesticus, Felis catus
           => kitty, kitty-cat, puss
           => mouser
           => alley cat
           => tom, tomcat
               => gib
           => Angora, Angora cat
           => Siamese cat, Siamese
               => blue point Siamese
       => wildcat
           => sand cat
           => European wildcat, catamountain, Felis silvestris
           => cougar, puma, catamount, mountain lion, painter, panther, Felis concolor
           => ocelot, panther cat, Felis pardalis
           => manul, Pallas's cat, Felis manul
           => lynx, catamount
               => common lynx, Lynx lynx
               => Canada lynx, Lynx canadensis
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T16:09:03+00:00Added an answer on June 6, 2026 at 4:09 pm

    You have got a sorted tree list here already. Each next line is either a child of the previous line or a sibling. So you can process over the list, get the name of an item, gain the level an item is in by it’s indentation and create an element out of it.

    1 Line <=> 1 Element (level, name)
    

    So every element has a name and zero or more children. From the input it can also be said which level it belongs to.

    An element can be represented as an array, in which it’s first value is the name and the second value is an array for the children.

    As the list is sorted, we can use a simple map, which per level is an alias to the children of a certain level. So with the level each element has, we can add it to the stack:

        $self = array($element, array());
        $stack[$level][] = &$self;
        $stack[$level + 1] = &$self[1];
    

    As this code-example shows, the stack/map for the current level is getting $self as children added:

        $stack[$level][] = &$self;
    

    The stack for the level one higher, get’s the reference to the children of $self (index 1):

        $stack[$level + 1] = &$self[1];
    

    So now per each line, we need to find the level. As this stack shows, the level is sequentially numbered: 0, 1, 2, ... but in the input it’s just a number of spaces.

    A little helper object can do the work to collect/group the number of characters in a string to levels, taking care that – if a level yet does not exist for an indentation – it is added, but only if higher.

    This solves the problem that in your input there is no 1:1 relation between the size of the indentation and it’s index. At least not an obvious one.

    This helper object is exemplary named Levels and implements __invoke to provide the level for an indent while transparently adding a new level if necessary:

    $levels = new Levels();
    echo $levels(''); # 0
    echo $levels('    '); # 1
    echo $levels('    '); # 1
    echo $levels('      '); # 2
    echo $levels(' '); # Throws Exception, this is smaller than the highest one
    

    So now we can turn indentation into the level. That level allows us to run the stack. The stack allows to build the tree. Fine.

    The line by line parsing can be easily done with a regular expression. As I’m lazy, I just use preg_match_all and return – per line – the indentation and the name. Because I want to have more comfort, I wrap it into a function that does always return me an array, so I can use it in an iterator:

    $matches = function($string, $pattern)
    {
        return preg_match_all($pattern, $string, $matches, PREG_SET_ORDER)
            ? $matches : array();
    };
    

    Using on input with a pattern like

    /^(?:(\s*)=> )?(.*)$/m
    

    will give me an array per each line, that is:

    array(whole_line, indent, name)
    

    You see the pattern here? It’s close to

    1 Line <=> 1 Element (level, name)
    

    With help of the Levels object, this can be mapped, so just a call of a mapping function:

    function (array $match) use ($levels) {
        list(, $indent, $name) = $match;
        $level = $levels($indent);
        return array($level, $name);
    };
    

    From array(line, indent, name) to array(level, name). To have this accessible, this is returned by another function where the Levels can be injected:

    $map = function(Levels $levels) {
        return function ...
    };
    $map = $map(new Levels());
    

    So, everything is in order to read from all lines. However, this needs to be placed into the the tree. Remembering adding to the stack:

    function($level, $element) use (&$stack) {
        $self = array($element, array());
        $stack[$level][] = &$self;
        $stack[$level + 1] = &$self[1];
    };
    

    ($element is the name here). This actually needs the stack and the stack is actually the tree. So let’s create another function that returns this function and allow to push each line onto the stack to build the tree:

    $tree = array();
    $stack = function(array &$tree) {
        $stack[] = &$tree;
        return function($level, $element) use (&$stack) {
            $self = array($element, array());
            $stack[$level][] = &$self;
            $stack[$level + 1] = &$self[1];
        };
    };
    $push = $stack($tree);
    

    So the last thing to do is just to process one element after the other:

    foreach ($matches($input, '/^(?:(\s*)=> )?(.*)$/m') as $match) {
        list($level, $element) = $map($match);
        $push($level, $element);
    }
    

    So now with the $input given this creates an array, with only (root) child nodes on it’s first level and then having an array with two entries per each node:

    array(name, children)
    

    Name is a string here, children an array. So this has already done the list to array / tree here technically. But it’s rather burdensome, because you want to be able to output the tree structure as well. You can do so by doing recursive function calls, or by implementing a recursive iterator.

    Let me give an Recursive Iterator Example:

    class TreeIterator extends ArrayIterator implements RecursiveIterator
    {
        private $current;
    
        public function __construct($node)
        {
            parent::__construct($node);
        }
    
        public function current()
        {
            $this->current = parent::current();
            return $this->current[0];
        }
    
        public function hasChildren()
        {
            return !empty($this->current[1]);
        }
    
        public function getChildren()
        {
            return new self($this->current[1]);
        }
    }
    

    This is just an array iterator (as all nodes are an array, as well as all child nodes) and for the current node, it returns the name. If asked for children, it checks if there are some and offers them again as a TreeIterator. That makes using it simple, e.g. outputting as text:

    $treeIterator = new RecursiveTreeIterator(
        new TreeIterator($tree));
    
    foreach ($treeIterator as $val) echo $val, "\n";
    

    Output:

    \-cat, true cat
      |-domestic cat, house cat, Felis domesticus, Felis catus
      | |-kitty, kitty-cat, puss
      | |-mouser
      | |-alley cat
      | |-tom, tomcat
      | | \-gib
      | |-Angora, Angora cat
      | \-Siamese cat, Siamese
      |   \-blue point Siamese
      \-wildcat
        |-sand cat
        |-European wildcat, catamountain, Felis silvestris
        |-cougar, puma, catamount, mountain lion, painter, panther, Felis concolor
        |-ocelot, panther cat, Felis pardalis
        |-manul, Pallas's cat, Felis manul
        \-lynx, catamount
          |-common lynx, Lynx lynx
          \-Canada lynx, Lynx canadensis
    

    If you’re looking for more HTML output control in conjunction with an recursive iterator, please see the following question that has an example for <ul><li> based HTML output:

    • How can I convert a series of parent-child relationships into a hierarchical tree? (Should as well have some other insightful information for you)

    So how does this look like all together? The code to review at once as a gist on github.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

My char array would be looking something like below, Org_arr[1first line text------2second line text----3third
I would like to convert a yyyy-mm-dd to something like this: Saturday, 2 October
I would like to convert some value from a XML attribute into valid HTML
I would like to convert something like: <property name='aoeu' value='a,o,e,u'/> to: <path id='ueoa'> <pathelement
I'm working on a project that requires to convert html email into text. Below
I got the below code which I would like to convert to a string
I would like to convert data from a table to an XML file. The
I would like to convert from an image (like jpg or png) to PDF.
I would like to convert BufferedImage to an image that will display on JSP
I would like to convert this string foo_utf = u'nästy chäräctörs with å and

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.