3

I've got an array ($categories_final), looks similar to this:

Array
(
    [0] => Accessories/Apron
    [1] => Accessories/Banners
    [2] => Accessories/Belts
    [3] => Brand/Brand1
    [4] => Brand/Brand2
    [5] => Apparel/Men/Belts
    [6] => Apparel/Men/Socks
    [7] => Apparel/Women/Leggings
)

I'm trying to get it to look like this so I can add it to a database as my store's category structure:

Array
(
    [Accessories] => Array
        (
            [0] => Apron
            [1] => Banners
            [2] => Belts
        )
    [Apparel] => Array
        (
            [0] => Men => Array
                (
                    [0] => Belts
                    [1] => Socks
                )
            [1] => Women => Array
                (
                    [0] => Leggings
                )
        )

        ...etc

Here's what I've got so far, but I am under able to figure out how to add the children under Men/ & Women/:

$categories = array();
foreach ($categories_final as $cat) {
    $levels = explode('/', $cat);
    if (isset($categories[$levels[0]])) {
        if (!in_array($levels[1], $categories[$levels[0]])) {
            $categories[$levels[0]][]= $levels[1];
        }
    }
    else {
        $categories[$levels[0]][]= $levels[1];
    }
}
print_r($categories);

Again, I'm stuck on how to add the /Belts, /Socks & /Leggings under their respective parents.

Any helps is appreciated, thanks!

3 Answers3

2

Since there can be an unlimited amount of branching, you should probably have a recursive solution. I tried my best and got this code:

$arr = ['Accessories/Apron', 'Accessories/Banners', 'Accessories/Belts','Brand/Brand1','Brand/Brand2',
        'Apparel/Men/Belts', 'Apparel/Men/Socks', 'Apparel/Women/Leggings'];

$final = [];
foreach ($arr as $branch) {
    $temp = branchRecursive($branch);
    $final = array_merge_recursive($final, $temp);
}



function branchRecursive($branch) {
    // explode only first
    $newBranch = explode('/', $branch, 2);

    // A leaf, no more branches
    if(count($newBranch) != 2) {

        return $newBranch[0];
    }

    $array [ $newBranch[0] ]= branchRecursive($newBranch[1]);
    return $array;

}

it returns this:

Array
(
    [Accessories] => Array
        (
            [0] => Apron
            [1] => Banners
            [2] => Belts
        )

    [Brand] => Array
        (
            [0] => Brand1
            [1] => Brand2
        )

    [Apparel] => Array
        (
            [Men] => Array
                (
                    [0] => Belts
                    [1] => Socks
                )

            [Women] => Leggings
        )

)

The only thing different from your code is

[Women] => Leggings

instead of

[0] => Leggings

But I want to sleep and my head is not working, so if anyone can point out what to change, I would be thankful. I hope it will not be much of an issue:)

Danielius
  • 852
  • 5
  • 23
  • 1
    HA! This is exactly why I had to ask you guys :) ...many thanks for your solution, this is pretty much what I was looking for (combined with the one above) - thanks again! – yooooooooooo Jun 08 '20 at 13:49
  • 1
    @yooooooooooo glad to help;) thanks for and interesting and good quality question. Becoming pretty rare here ;D – Danielius Jun 08 '20 at 15:01
1

One method is to "convert" the array items to json and then decode to array.

I first make a mid step where the string become invalid json, but then the preg_replace make the inner {} to [] to make it valid.
Then merge with result.

$result =[];
foreach($arr as $val){
    $count = count(explode("/", $val));
    $str = '{"' . str_replace('/', '":{"', $val) . '"}' . str_repeat("}", $count-1);
    $json = preg_replace("/(.*)(\{)(.*?)(\})/", "$1[$3]", $str);
    $result = array_merge_recursive($result, json_decode($json, true));
}

Print_r($result);

https://3v4l.org/5i3SW

Andreas
  • 23,610
  • 6
  • 30
  • 62
  • This is interesting and saves a lot of space...I went with the other answer as it fits more in with my style, but your solution is something I am going to play with! Thank you! – yooooooooooo Jun 08 '20 at 13:48
1

this code gives you the ability to make as many sub branches as you want.

$source = array('Accessories/Apron ' ,
        'Accessories/Banners',
        'Accessories/Belts',
        'Brand/Brand1',
        'Brand/Brand2',
        'Apparel/Men/Belts',
        'Apparel/Men/Socks',
        'Apparel/Women/Leggings'
    );

function convert($categories_final) {
    $categories = array();
    foreach ($categories_final as $cat) {
        $levels = explode('/', $cat);
        // get category
        $category_name = $levels[0];
        array_shift($levels);
        if(!array_key_exists($category_name,$categories)) {
            $categories[$category_name] = array();
        }
        $tmp = &$categories[$category_name] ;
        foreach($levels as $index => $val){
            if($index + 1 === count($levels) ){
                $tmp[] = $val; 
            } else {
                $i = find_index($tmp , $val);
                if( $i == count($tmp) ) { // object not found , we create a new sub array
                    $tmp[] = array($val => array());
                }
                $tmp = &$tmp[$i][$val];
            }
        }

    }
    return $categories;
}

function find_index($array , $key) {
    foreach($array as $i => $val ) {
        if(is_array($val) && array_key_exists($key , $val) ){
            return $i ;
        }
    }
    return count($array);
}

print_r(convert($source));

this is the result

Array
(
    [Accessories] => Array
        (
            [0] => Apron 
            [1] => Banners
            [2] => Belts
        )
    [Brand] => Array
        (
            [0] => Brand1
            [1] => Brand2
        )

    [Apparel] => Array
        (
            [0] => Array
                (
                    [Men] => Array
                        (
                            [0] => Belts
                            [1] => Socks
                        )
                )
            [1] => Array
                (
                    [Women] => Array
                        (
                            [0] => Leggings
                        )
                )
        )

)
Ehsan Nazeri
  • 771
  • 1
  • 6
  • 10