-3

I have an array containing namespace information:

$array = [
    ['App', 'Classes', 'Auth'],
    ['App', 'Classes', 'Auth'],
    ['App', 'Classes', 'Middleware'],
    ['App', 'Classes', 'Phone'],
    ['App', 'Classes', 'Auth'],
    ['App', 'Mail'],
    ['App', 'Mail', 'Sender'],
    ['App', 'Box'],
];

Now I want to build a single array or object that should show the namespace information in an hirachic way:

$result = [
    ['App' => 
        ['Classes' => 
            [
                'Auth',
                'Middleware',
                'Phone',
            ]
        ],
        ['Mail' => 
            ['Sender']
        ],
        ['Box'] => []
    ]
]

I have tried some recursive functions, but all I get is a flat array...


private function createNamespaceHirachy( $namespaces ) {


        foreach ($namespaces as $index => $namespace) {
            $namespaces[$namespace] = [];
            $namespaces[$namespace] = $this->createNamespaceHirachy($namespaces[$namespace]);
        }


    return $namespaces;
}

Sorry, it may be much more simple, but I'm brainstuck :-/

6
  • 4
    Show us that recursive function which you tried. Commented May 27, 2019 at 12:34
  • 2
    Please show us what you tried (and with what exact results), and explain your reasoning. Commented May 27, 2019 at 12:34
  • 1
    This may help you: stackoverflow.com/questions/56135624/… Commented May 27, 2019 at 12:34
  • 1
    You need not use recursion at all. Commented May 27, 2019 at 12:38
  • So this can never go four levels deep? Commented May 27, 2019 at 12:40

2 Answers 2

2
<?php

$array = [
    ['App', 'Classes', 'Auth'],
    ['App', 'Classes', 'Auth'],
    ['App', 'Classes', 'Middleware'],
    ['App', 'Classes', 'Phone'],
    ['App', 'Classes', 'Auth'],
    ['App', 'Mail'],
    ['App', 'Mail', 'Sender'],
    ['App', 'Box'],
];

$hierarchy = [];

foreach($array as $each_data){
    $curr_hierarchy = &$hierarchy;
    foreach($each_data as $each_namespace){
        if(!isset($curr_hierarchy[$each_namespace])){
            $curr_hierarchy[$each_namespace] = [];
        }

        $curr_hierarchy = &$curr_hierarchy[$each_namespace];
    }
}

print_r($hierarchy);

Demo: https://3v4l.org/AVVZI

  • We loop over each hierarchical data in $array one by one.
  • We initialize the final resulting array as $hierarchy in the above code.
  • Now, inside the inner foreach loop, we maintain a current hierarchy stage. In other words, $curr_hierarchy contains the current level we are in.
  • As we loop over inside the inner foreach loop, if the current stage does not have the namespace as it's key, we assign it and go one level further deep by passing it as the new current hierarchy.
  • Note that the pass by reference & is necessary to reflect changes overall to the array, else, it creates a new clone keeping your final array empty.
  • You may also notice the child elements itself being an array as well. I think that's fine for your current context, but do let me know if that wasn't what you desired.
Sign up to request clarification or add additional context in comments.

11 Comments

@DaFunkyAlex Happy to help :)
@DaFunkyAlex your expected output is different from this answer output. Please confirm once.
@vivek_23 your output is not same what OP asked for.Auth needs to be a value inside classes array not an empty array with index auth and so on for others
@DaFunkyAlex but the answer isn't correct. It's not what you asked for.
If the array is going to be json_encoded and sent out to users or clients then I think it would matter.
|
1

Here is snippet for your scenario

$results = json_decode(json_encode($array)); // converting to object to play
$tree    = null;
foreach ($results as $result) {
    // checking first getting address of it to play
    $thisref                          = &$refs->{$result[0]}; 
    $tree->{$result[0]}               = &$thisref;
    // checking for level 1 if not empty
    $thisref                          = &$refs->{$result[1]};
    $tree->{$result[0]}->{$result[1]} = &$thisref;
    // checking for level 2 if not empty
    if (!empty($result[2])) {
        $thisref                                        = &$refs->{$result[2]};
        $refs->{$result[0]}->{$result[1]}[] = $result[2];//&$thisref;
        $refs->{$result[0]}->{$result[1]} = array_unique($refs->{$result[0]}->{$result[1]});
    }

}
// finally converting back to array
print_r(json_decode(json_encode($tree), true));

Working demo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.