Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am trying to create a multidimensional array from a linear array.

This array:

$array = array(
    array('level-one', 'level-two', 'level-three'),
    array('level-one', 'level-two', 'level-three', 'level-four'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 1'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 2'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 3'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 4'),
);

Into:

$multi = array(
    'level-one' => array(
        'level-two' => array(
            'level-three' => array(
                'level-four' => array(
                    'item 1',
                    'item 2',
                    'item 3',
                    'item 4',
                )
            )
        )
    )
);

I guess I should go somehow recursive but I can't find a recursive solution logic.

share|improve this question
    
What have you tried so far? –  TiMESPLiNTER Jan 7 at 14:35
    
level count is fixed? –  kumar_v Jan 7 at 14:35
4  
I must ask why you're doing this. Is this something where you are getting an array from elsewhere that you need to manipulate, or are you generating it? This looks similar to XML; was it originally such? Maybe going this route isn't the right direction and we can do it in another step in the process. –  Andrew Jan 7 at 14:36
    
both are multidimensional arrays –  MrHunter Jan 7 at 14:58
    
Looking past why you would ever need this, I think the approach in this answer should work with minimal modifications. It is however written in Java, but the approach is rather simple. If you answer shows up here I'll take the time to convert it to PHP after dinner. –  atomman Jan 7 at 15:01
show 1 more comment

4 Answers

up vote 1 down vote accepted

You can give this a go

function to_nested($ary){
    $a = array();
    foreach ( $ary as $rec ){
        $b = &$a;
        $node = null;
        foreach ( $rec as $f ){
            if ( $node !== null ){
                if ( !isset($b[$node]) ){
                    $isleaf = array_search($node,$b);
                    if ( $isleaf !== false )
                        unset($b[$isleaf]);
                    $b[$node] = array();
                }
                $b = &$b[$node];
            }
            $node = $f;
        }
        //push leaf
        if ( empty($b) ){
            $b = array();
        }
        array_push($b, $f);
    }

    return $a;
}

$array = array(
    array('level-one', 'level-two', 'level-three'),
    array('level-one', 'level-two', 'level-three', 'level-four'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 1'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 2'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 3'),
    array('level-one', 'level-two', 'level-three', 'level-four', 'item 4'),
);

print_r(to_nested($array));

result:

Array (
    [level-one] => Array
        (
            [level-two] => Array
                (
                    [level-three] => Array
                        (
                            [level-four] => Array
                                (
                                    [0] => item 1
                                    [1] => item 2
                                    [2] => item 3
                                    [3] => item 4
                                )
                        )
                )
        )
)

I'm not sure what the rules are for your input array so I'd suggest that you play around with different valid inputs to see if the results of this function work for you.

share|improve this answer
    
Just wonderfull and perfect! –  Gilberto Albino Jan 7 at 15:30
    
glad to hear it. oops just noticed, you may surround the //push leaf code with if ( !isset($b[$node]) ){} to prevent a leaf from being created if an array with the same key name already exists on that same level. which could happen if say "array('level-one', 'level-two', 'level-three')," was at the bottom of your example input array instead of at the top. –  armsteady Jan 7 at 15:39
    
I thinks the last item of the array must be associative too. Not [0] => item 1 is allowed –  Gilberto Albino Jan 7 at 18:12
add comment

Try

$data=array();
for($i=0;$i<sizeof($array);$i++){
        $tmp=array();
    $data =  array_unique(array_merge($data,$array[$i]));
}

Now duplicate entries have been removed. Now create a multidimensional array

$output=array();
$tmp = &$output;
foreach($data as &$val){
  if(strpos($val,'level') !==false ){
     if (!is_array($tmp)){
          $tmp = array();
      }
      $tmp = &$tmp[$val];

  }else{
    $tmp[] = $val;
  }
}

echo "<pre>";
print_r($output);
exit();
share|improve this answer
add comment
$last_array = end($array);

// Create an array like your structure, i.e.
// ['level-one', 'level-two', 'level-three', 'level-four'].
$structure = array_slice($last_array, 0, -1);

// Remove all arrays, but the ones with items.
$neat_array = array_filter($array, function($current_array) use ($last_array) {
    return sizeof($current_array) === sizeof($last_array);
});

// Create an array of just your items, i.e.
// ['item 1', 'item 2', 'item 3', 'item 4'].
$items = array_map(function($item) use ($structure) {
    return $item[sizeof($structure)];
}, $neat_array);

// And the final product.
$multi = array_reduce(array_reverse($structure), function($result, $item) {
    return array($item => $result);
}, $items);

print_r($multi);

And the output will be as desired:

Array
(
    [level-one] => Array
        (
            [level-two] => Array
                (
                    [level-three] => Array
                        (
                            [level-four] => Array
                                (
                                    [2] => item 1
                                    [3] => item 2
                                    [4] => item 3
                                    [5] => item 4
                                )

                        )

                )

        )

)
share|improve this answer
add comment
 $array1=array(
  'level1'=>array(
     'level2'=>array(
       'level3'=>array(
          'level4'=>array(
             'A'=>'value1',
                 'B'=>'value2',
                 'C'=>'value3',
                 'D'=>'value4'
             )
           )
         )
       )
    );
    print_r($array1);
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.