2016-11-28 19 views
1

私はPHPの多次元配列を持っていて、各ノードはその下に親ノードをリストしています。私は出力を各ノードが任意の子ノードを列挙し、配列内の一意のパスのみを列挙して階層的にリストアップするように配列を変換しようとしています。PHP多次元配列はすべてのユニークなパスを見つける

例えば、この入力配列:

$input = [ 

     [ 
      "name" => "home", 
      "parents" => [], 
     ], 
     [ 
      "name" => "newslist", 
      "parents" => [ 
       [ 
        "name" => "home", 
        "parents" => [], 
       ], 
      ], 
     ], 
     [ 
      "name" => "newsdetail", 
      "parents" => [ 
       [ 
        "name" => "newslist", 
        "parents" => [ 
         [ 
          "name" => "home", 
          "parents" => [], 
         ], 
        ], 
       ], 
       [ 
        "name" => "home", 
        "parents" => [], 
       ], 
      ], 
     ], 
     [ 
      "name" => "knowledge", 
      "parents" => [], 
     ], 
    ]; 

万一出力この配列:

$output = [ 
     [ 
      "name" => "home", 
      "children" => [ 
       [ 
        "name" => "newslist", 
        "children" => [ 
         [ 
          "name" => "newsdetail", 
          "children" => [], 
         ], 
        ], 
       ], 
      ], 
     ], 
     [ 
      "name" => "knowledge", 
      "children" => [], 
     ], 
    ]; 
+4

あなたのコード/リサーチ –

+0

へようこそStackOverflowへようこそ!人々があなたの質問に答えるように促すために[質問する方法](http://stackoverflow.com/help/how-to-ask)を見てください。 – Nytrix

答えて

0

これはおそらく非常に良くな方法で行うことができるが、この方法で動作します。手続き的な機能だけが概念の証明として機能します。

<?php 

$input = [ 

    [ 
     "name" => "home", 
     "parents" => [], 
    ], 
    [ 
     "name" => "newslist", 
     "parents" => [ 
      [ 
       "name" => "home", 
       "parents" => [], 
      ], 
     ], 
    ], 
    [ 
     "name" => "newsdetail", 
     "parents" => [ 
      [ 
       "name" => "newslist", 
       "parents" => [ 
        [ 
         "name" => "home", 
         "parents" => [], 
        ], 
       ], 
      ], 
      [ 
       "name" => "home", 
       "parents" => [], 
      ], 
     ], 
    ], 
    [ 
     "name" => "knowledge", 
     "parents" => [], 
    ], 
]; 

//recursively get all parents and the level the parent is at 
function getParents($nodes,$level,&$parents) 
{ 
    foreach($nodes AS $key => $node) 
    { 
     $parents[ $node['name'] ] = array("name" => $node['name'], "level" => $level); 
     if(isset($node['parents']) && !empty($node['parents'])) 
     { 
      $level += 1; 
      getParents($node['parents'],$level,$parents); 
     } 
    } 
} 

//sort the parents by level 
function sortParentsByLevel($a, $b) 
{ 
    if ($a['level'] == $b['level']) { 
     return 0; 
    } 
    return ($a['level'] > $b['level']) ? -1 : 1; 
} 

//find the output path based on parents array to add new value to 
function setValueFromPath(&$paths, $parents, $value) 
{ 
    $dest = &$paths; 

    if(empty($parents)) 
    { 
     if(!isset($dest[$value])) 
      $dest[$value] = array(); 

    } else { 

     $finalNode = array_pop($parents); 

     foreach ($parents as $parent) 
     { 
      $dest = &$dest[$parent]; 
     } 

     $dest[$finalNode][$value] = array(); 

    } 

} 

//init new variable 
$output = array(); 

//loop through each input node 
foreach($input AS $key => $node) 
{  

    //init a parent array 
    $parents = array(); 

    //if we have parents use the getParents method to set them 
    if(isset($node['parents']) && is_array($node['parents']) && !empty($node['parents'])) 
    { 
     getParents($node['parents'],1,$parents); 
    } 

    //sort the parents according to their level 
    uasort($parents, 'sortParentsByLevel'); 

    //we're only interested in the associative key 
    $parentKeys = array(); 
    foreach($parents AS $parent) 
    { 
     $parentKeys[] = $parent['name']; 
    } 

    //add the $node['name'] value in the appropriate parent array 
    setValueFromPath($output, $parentKeys, $node['name']); 

} 

echo '<pre>'; 
print_r($output); 
echo '</pre>'; 
die(); 

/* 
Array 
(
    [home] => Array 
     (
      [newslist] => Array 
       (
        [newsdetail] => Array 
         (
         ) 

       ) 

     ) 

    [knowledge] => Array 
     (
     ) 

) 
*/