从多个数组中创建一个数组

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

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

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.