Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

How can I transform array#1 into the array#2 structure using php ?

The first Array is the results of a database query on a list of Organisms, each organism is classified with it's Order, Family, Genus, Species. Hierarchically Species are the child classifications of various Genus, and Genus classifications are child classifications of various Families etc .

In namespace terms you could read it like so:

item at index[ 0] ---> Hemiptera.Miridae.Kanakamiris
item at index[ 1] ---> Hemiptera.Miridae.Neophloeobia.incisa

There is a kind of parent/child relationship between the keys of array#1 which is as follows:

  • 'Rank_Order' value is the parent of the 'Rank_Family' value
  • 'Rank_Family' value is the parent of the 'Rank_Genus' value
  • 'Rank_Genus' value is the parent of the 'Rank_Species' value

array#1:

Array
(
    [0] => Array
        (
            ['Rank_Order'] => 'Hemiptera'
            ['Rank_Family'] => 'Miridae'
            ['Rank_Genus'] => 'Kanakamiris'
            ['Rank_Species'] => ''
        )   
    [1] => Array
        (
            ['Rank_Order'] => 'Hemiptera'
            ['Rank_Family'] => 'Miridae'
            ['Rank_Genus'] => 'Neophloeobia'
            ['Rank_Species'] => 'incisa'
        )
    [2] => Array
        (
            ['Rank_Order'] => 'Hemiptera'
            ['Rank_Family'] => 'Noridae'
            ['Rank_Genus'] => 'Canelbia'
            ['Rank_Species'] => 'Arissa'
        )
)

The following array is the array structure i need: array#2:

Array(
    [name]     => 'Hemiptera'
    [children] => Array(

        [0] => Array(
            [name]     => 'Miridae'
            [children] => Array(

                [0] => Array(
                    [name]     => 'Kanakamiris'
                    [children] => Array(
                    )
                )
                [1] => Array(
                    [name]     => 'Neophloeobia'
                    [children] => Array(

                        [0] => Array(
                            [name] => 'incisa'
                            [children] => Array(
                            )
                        )
                    )
                )
            )
        )
        [1] => Array(
            [name]     => 'Noridae'
            [children] => Array(

                [0] => Array(
                    [name]     => 'Canelbia'
                    [children] => Array(

                        [0] => Array(
                            [name] => 'Arissa'
                            [children] => Array(
                            )
                        )
                    )
                )
            )
        )
    )
)

I see similar questions asked in stack overflow, though have not been able to use them in my case. eg. php-reorder-array-to-reflect-parent-id-hierarchy

share|improve this question
What's the motivation for the change and why not use OOP ? – alfasin Aug 16 '12 at 5:34
2d array can solve this – NullPoiиteя Aug 16 '12 at 5:35
2  
You say that similar questions aren't usable in your case, but don't provide us any details about your specific array structure... what is you question?? – orourkek Aug 16 '12 at 5:36
I want to take the first array and create the second array from it. I will edit the statement between the two code blocks to be a question, apologies – johowie Aug 16 '12 at 5:40
1  
it's not clear how does the first array translates into the second since the key-names are different. Also, why not convert it into json directly, why do you have to go through another phase of a nested array ? – alfasin Aug 16 '12 at 5:49
show 10 more comments

1 Answer

I don't think this will be super-efficient for really large arrays, but it works for your scenario (here's a sample).

 $array = ...
 $levels = array('Rank_Order', 'Rank_Family', 'Rank_Genus', 'Rank_Species');

 function get_children($parent, $lev, $orig, $levels){
     if($lev + 1 > count($levels)){
          return array();
     }

     $seen = array();
     $children = array();
     foreach($orig as $node){
         if($node[$levels[$lev]] == $parent && !in_array($node[$levels[$lev+1]], $seen)){
             $seen[] = $node[$levels[$lev+1]];
             $children[] = get_children($node[$levels[$lev+1]], $lev+1, $orig, $levels);
         }
     }
     return array('name' => $parent, 'children' => $children);
 }

 function hier($orig, $levels){
     $seen = array();
     $result = array();
     foreach($orig as $node){
         if(!in_array($node[$levels[0]], $seen)){
              $seen[] = $node[$levels[0]];
              $result[] = get_children($node[$levels[0]], 0, $orig, $levels);
         }
     }
     return $result;
 }

 print_r($array);
 print_r(hier($array, $levels));
share|improve this answer
it seems $result needs to be pushed in somewhere. i'm trying to understand where – johowie Aug 17 '12 at 5:49
@johowie: ah, I missed the initialization in the second function, but it's not actually required. You just need to capture the output of a call to hier – Mark Elliot Aug 17 '12 at 12:04
that is indeed working as required, though computation time does seem to be a problem. – johowie Aug 18 '12 at 23:42
1  
@johowie, it's not clear to me that one can do better. This will take at most O(MN) time for depth M and N distinct root elements, and should do much better for complete hierarchies. Here, M is constant, so the algorithm's complexity, believe it or not, is linear. – Mark Elliot Aug 19 '12 at 3:49
in hier() it seems the return $seen; should be return $result;, is that correct ?. when I run this php script it takes ages on my local host (MAMP) and with arrays larger than a handful of nodes it simply times out with a server error. Your example @Mark on ideone.com works considerably faster. I cant work out why my localhost doesn't like this ! – johowie Aug 20 '12 at 5:44
show 1 more 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.