duanbo2048
2016-11-17 18:22 阅读 39
已采纳

递归 - 如何构造没有id的数据树,数据是模糊的。

Please refer to the solution, this has been solved.

I have the following dataset and no ids are provided, trying to get this completed using recursion.

Should I attempt this or should I go another route? Because there are no ids.

After a filter on each attribute the root is gender, node 1 is category and end node is label. I have tried to use array_merge_recursive, array_push and I have tried to construct my own recursive pattern but nothing appears to get the pattern I want.

JSON data:

[{"label":"Shirts","tag":"M_SHIRT","gender":"Men","category":"Clothing"},
{"label":"Pants","tag":"M_PANT","gender":"Men","category":"Clothing"},
{"label":"Shorts","tag":"M_SHORT","gender":"Men","category":"Clothing"},
{"label":"Casual","tag":"M_SHOE_CASUAL","gender":"Men","category":"Shoes"},
{"label":"Tennis","tag":"M_SHOE_TENNIS","gender":"Men","category":"Shoes"},
{"label":"Watches","tag":"M_ACCESS_WATCH","gender":"Men","category":"Accessories"},
{"label":"Belts","tag":"M_ACCESS_BELT","gender":"Men","category":"Accessories"},
{"label":"Ties","tag":"M_ACCESS_TIE","gender":"Men","category":"Accessories"}]

Men
 ->Accessories 
   ->Watches
   ->Belts
   ->Ties
 ->Clothing
   ->Pants
   ->Shirts
   ->Shorts  
 ->Shoes
   ->Casual
   ->Tennis

Here is my PHP code for the recursion which is messy:

  function buildSideBar($searchLayers){
        try{
            $sidebar;
            $count = 0;
            foreach($searchLayers[$count] as $root){
                //$sideBarData[]=array("root"=>$root);
                $sideBarData[]=$root;
                $searchLayers[$count]='';
                $this->addChildren($sideBarData,$searchLayers,1,$root, $count);
                $count++;
            }
            var_dump($sideBarData);
        }catch (Exception $ex){
            log($ex);
        }

    }

    function addChildren(&$sideBarData,$layers,$level,$parent,$count){
        if(!empty($layers[$level]) && is_array($layers[$level])){
            foreach($layers[$level] as $child){
                //check if child is a node
                if($this->verifyChildBelongsToParent($child,$parent)){
                    if($level==1)
                    {
                        $count = 0;
                       // $sideBarData = array_merge_recursive($sideBarData, array("root"=>array("child".$level=>$child)));
                        $sideBarData[0][$level] = $child;
                    }
                    else
                    {
                        $sideBarData[][][$level] = $child;
                    }
                    $parents[]=$parent;
                    $parents[]=$child;
                    //var_dump($parents);
                    if($level<3)
                    {
                      //  $this->addChildren($sideBarData,$layers,$level++,$parents);
                    }

                }

                //
            }
        }

    }

    function verifyChildBelongsToParent($child,$parent){
        //var_dump($this->categoryData);break;
        foreach($this->categoryData as $category){

            if(is_array($parent) && sizeof($parent)>1){
                echo 'Child' . $child;
                echo 'PARENTS ';
                var_dump($parent);
                var_dump($category);

                if(strcmp($category->getGender(),$parent[0])==0 && strcmp($category->getCategory(),$parent[1])==0)
                {
                    var_dump($child);
                    echo 'Add child ' . $child;
                    return true;
                }

            }
            else{
                //echo 'check if ' . $parent .' has child ' . $child;
                if(strcmp($category->getGender(),$parent)==0)
                {
//                    var_dump($parent);
//                    var_dump($child);
                   // echo 'Add Child';
                    return true;
                }

            }
        }
        return false;


    }

Here is the $searchLayers data that I pass in:

Array
(
    [0] => "MEN",
    [1] => Array(
          [0]=>'Accessories',
          [1]=>'Clothing',
          [2]=>'Shoes'
        ),
    [2] =>Array(
          [0]=>'Belts',
          [1]=>'Casual',
          [2]=>'Shirts',
          [3]=>'Shorts',
          [4]=>'Tennis',
          [5]=>'Ties',
          [6]=>'Watches'
    )
);
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    doudou32012 doudou32012 2016-11-18 13:33

    So here's my solution, there maybe a better one, but I attempted 3 different techniques always thinking that this could be scalable.

    I placed the following limitations on the design, the side menu bar can only be 3 levels deep.

    With that I initially sorted the data to find out the grandparent, parent, child which is detailed in the $searchLayers above, but I passed this into as 3 separate arrays ($layer1, $layer2, $layer3) which comply with the parental hierarchy.

    Here is the code, which all starts by calling the top most function function buildSideMenu($layer1,$layer2,$layer3)

    //starts the construction of a side menu and adds each layer of children to the parent
    function buildSideMenu($layer1, $layer2, $layer3){
      $sideMenu = '<ul class="nav nav-stacked">';
      foreach($layer1 as $layer){
          $sideMenu.= '<li><a class="expandable" href="#">'.$layer.'</a></li>';
          //adds children founded to the parent
          $sideMenu .= $this->buildSideMenuChildern($layer,$layer2,$layer3);
    
      }
      $sideMenu .= '</ul>';
      $this->sideMenu = $sideMenu;
    }
    
    //builds on children to a side bar that belogn to a parent
    function buildSideMenuChildern($parent,$layer1,$layer2=''){
        $entries ='';
        foreach($layer1 as $layer){
            //deter mines if the child belongs to the parent
            if($this->isLayerParentMatch($layer,$parent)){
                //if this child has it's own childern, process needs to be repeated, else child is an leaf (aka end node)
                if(!empty($layer2)){
                    $entries .= '<li><a class="expandable" href="/'.$this->getTag($layer).'">'.$layer.'</a></li>';
                    $entries .= $this->buildSideMenuChildern(array($parent,$layer),$layer2);
                }else{
                    $entries .= '<li><a href="/'.$this->getTag($layer).'">'.$layer.'</a></li>';
                }
            }
        }
        $entries = (!empty($entries))? '<ul style="display:block;">'.$entries.'</ul>':$entries;
        return $entries;
    }
    
    //populates href with tag if one is available, converts text to lower case
    function getTag($label){
        foreach($this->categoryData as $category){
            if(strcmp($label,$category->getLabel())==0)
            {
                return $category->getTag();
            }
        }
        return '#'.  strtolower($label);
    }
    
    //determines if child is associated with all parents provided
    function isLayerParentMatch($child,$parent){
        if(empty($child) || empty($parent)) return false;
        foreach($this->categoryData as $category){
            if(!is_array($parent) && strcmp($category->getGender(),$parent)==0 && strcmp($category->getCategory(),$child)==0)
            {
                return true;
            }else if(strcmp($category->getGender(),$parent[0])==0 
                    && strcmp($category->getCategory(),$parent[1])==0
                    && strcmp($category->getLabel(),$child)==0){
                return true;
            }
        }
        return false;
    }
    
    function getSideMenu(){
            return $this->sideMenu;
    }
    

    Please also note, that I converted the json data into a PHP class of Category in which I had getters and setters for each of the attributes defined in the json data. This class has also been omitted from this code.

    点赞 评论 复制链接分享

相关推荐