2014-12-08 2 views
0

나는 stdclasses가있는 1 차원 배열을 가지고 있는데,이 객체는 이름과 "abh"속성을 가지고 있습니다. 이제 다차원 배열과 같은 트리 뷰를 얻고 싶습니다. 데이터베이스의 데이터가 이전에 호출되는 함수에서 camesPHP 부모 배열로 다차원 배열로 변환

$ar = array(
    (object)array("name" => "Test1","otherstuff"=>array(),"abh"=>""), 
    (object)array("name" => "Test2","otherstuff"=>array(),"abh"=>"Test1"), 
    (object)array("name" => "Test3","otherstuff"=>array(),"abh"=>"Test1"), 
    (object)array("name" => "Test4","otherstuff"=>array(),"abh"=>"Test1"), 
    (object)array("name" => "Test5","otherstuff"=>array(),"abh"=>"Test1"), 
    (object)array("name" => "Test6","otherstuff"=>array(),"abh"=>"Test5"), 
    (object)array("name" => "Test7","otherstuff"=>array(),"abh"=>"Test5"), 
    (object)array("name" => "Test8","otherstuff"=>array(),"abh"=>array("Test5","Test7")), 
    (object)array("name" => "Test9","otherstuff"=>array(),"abh"=>"Test8"), 
    (object)array("name" => "Test10","otherstuff"=>array(),"abh"=>"Test6"), 
    (object)array("name" => "Test11","otherstuff"=>array(),"abh"=>"Test9"), 
); 

, 하지를 내 배열은 다음과 같습니다 말할 수 있습니다. 결과는 다음과 같습니다.

Array 
(
[0] => stdClass Object 
    (
     [name] => Test1 
     [otherstuff] => Array 
      (
      ) 

     [abh] => 
    ) 

[1] => stdClass Object 
    (
     [name] => Test2 
     [otherstuff] => Array 
      (
      ) 

     [abh] => Test1 
    ) 
[...] 
) 

이제이 배열은 "abh"속성으로 정렬됩니다. "abh"가 비어있는 첫 번째 것, 그 뿌리, 다른 모든 것은 그것의 자식이 될 것입니다. 그래서 함수는 보조 자식이있는 경우 에 "childs"속성을 추가해야합니다.. 그러나 이제는 "abh"가 배열 자체가 될 수 있고 n 부모에게 재 할당되기 때문에이 유형은 특별한 유형입니다. 위의 예에서 Test8은 Test5 및 Test7 (복제)의 하위 항목이어야합니다.

저는 이것을 재귀 함수로 처리하려고 시도했으며 foreach에서 루프합니다. 거기에서 그것은 요소의 abh를 검사합니다. 부모는 존재하지만 작동하지 않습니다. array_filter() doenst 내가 원하는 것처럼해라. 그것에 대해

Array 
(
    [Test1] => stdClass Object 
     (
      [name] => Test1 
      [otherstuff] => Array() 
      [abh] => 
      [childs] => Array 
       (
        [Test2] => stdClass Object 
         [...] and so on 
       ) 
     ) 
) 

아이디어 :

그래서, 나는이 결과를 원하는? 나는 반환 된 배열에 얼마나 많은 "레벨"이 있는지 알지 못합니다. 얼마나 많은 입력 개체와 "abh"- 할당이 있는지 알고 있습니다. 초는 "abh"배열이 최대 10 개의 "부모"를 가질 수 있다는 것입니다.

도움 주셔서 감사합니다. requestet


내 비 작업이 "정렬"

function checkABH(&$return,&$ar,$deph) { 

    // clone all with array-abh 
    $count = count($ar); 
    for($x=0;$x<$count;$x++) {#$ar as$key=>$val) { 
     if(is_array($ar[$x]->abh)) { 
      $clone = $ar[$x]; 
      foreach($ar[$x]->abh as$abh) { 
       #echo "<br>$x @@ $abh"; 
       $clone->abh = $abh; 
       $ar[]  = $clone; 
       #echo '<pre>'.print_r($clone,true).'</pre>'; 
      } 
      // delete array-abh-element 
      unset($ar[$x]); 
     } 
    } 

    echo '<pre>'.print_r($ar,true).'</pre>'; 
    echo '</div>'; 
    echo '<div style="float:left;width:auto;margin:0px 10px;"><h3>Result:</h3>'; 

    // pass to sorter 
    checkABH_a($return,$ar,$deph); 
} 

function checkABH_a(&$return,&$ar,$deph) { 

    $test_abhs = array(); 

    foreach($ar as$key=>$val) { 

     $val->childs = array(); 

     if(isset($return[$deph])&&isset($return[$deph]->name)&&$val->abh==$return[$deph]->name) { 
      $return[$deph]->childs[] = $val; 
      unset($ar[$key]); 
     } elseif($val->abh==$deph) { 
      $return[$val->abh] = $val; 
      unset($ar[$key]); 
     } else { 
      $test_abhs[] = $val->abh; 
     } 
    } 

    if(count($test_abhs)>0) { 
     $test_abhs = array_unique($test_abhs); 
     #echo '<pre>'.print_r($test_abhs,true).'</pre>'; 
     foreach($test_abhs as$abh) { 
      checkABH_a($return,$ar,$abh); 
     } 
    } 
} 

echo '<div style="float:left;width:260px;border-right:1px solid #cccccc;margin:0px 10px;"><h3>Input</h3>'; 
echo '<pre>'.print_r($ar,true).'</pre>'; 
echo '</div>'; 
echo '<div style="float:left;width:260px;border-right:1px solid #cccccc;margin:0px 10px;"><h3>Cloned:</h3>'; 
$return = array(); 
checkABH($return,$ar,""); 
echo'<pre>'.print_r($return,true).'</pre>'; 
echo '</div>'; 
+0

그리고 ... 시도 했습니까? [좋은 질문을하는 법] (http : // stackoverflow.부모/자식/도움말/방법 - 묻기) – RiggsFolly

+0

내가 위에서 말한 것처럼, 그 빈까지 자체에 배열을 전달하는 재귀 함수 - 그것은 부모가 존재하는지 확인하고 그 아이를 넣어 -하지만 내 솔루션은 작동하지 않습니다 – UnskilledFreak

+0

당신의 솔루션을 잘 보여주고, 우리는 그것을 볼 수 있고 improvments/corrects를 제안 할 수있다. – RiggsFolly

답변

1

이 재귀 나무가 쉬워지고 있지 않습니다에 대한 prototyp을의 '여러 부모의 요구 사항에 무슨 일이 추가되고, -/어쨌든, 그것은 여전히 ​​재미있어 보입니다 ...

나는 이미 충분히 논평 한 것으로 생각하여 여기에 모든 코드를 문서화하지 않을 것입니다.

참고 : 'insertNode'기능을 이해하기 쉬웠다 있도록

  • 개별 항목을 (중복)이 '여러 부모를'변환.
  • 'stdClass'대신 'TreeNode'라는 클래스를 만들었으므로 나중에 메서드를 추가 할 수 있습니다. 코드에 대한

Working version of the code at Viper-7.com using PHP 5.3.18

모든 쿼리는 의견을 게시하고 난 대답 그들을 시도 할 것이다.

<?php // https://stackoverflow.com/questions/27360813/php-convert-array-to-multidimensional-array-by-parent-id 

$ar = array(
    (object) array("name" => "Test1", "otherstuff"=>array('parent is Test1'), "abh"=>""), 
    (object) array("name" => "Test2", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"), 
    (object) array("name" => "Test3", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"), 
    (object) array("name" => "Test4", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"), 
    (object) array("name" => "Test5", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"), 
    (object) array("name" => "Test6", "otherstuff"=>array('parent is Test5'), "abh"=>"Test5"), 
    (object) array("name" => "Test7", "otherstuff"=>array('parent is Test5'), "abh"=>"Test5"), 
    (object) array("name" => "Test8", "otherstuff"=>array('parent is Test5 AND Test7'), "abh"=>array("Test5", "Test7")), 
    (object) array("name" => "Test9", "otherstuff"=>array('parent is Test8'), "abh"=>"Test8"), 
    (object) array("name" => "Test10", "otherstuff"=>array('parent is Test6'), "abh"=>"Test6"), 
    (object) array("name" => "Test11", "otherstuff"=>array('parent is Test9'), "abh"=>"Test9"), 
); 


/* 
* The requirement is that for any child then the parent must be in the tree already. 
*/ 

// Convert those parent with 'arrays of parents' into individual entries as it will make the insert 
// easier to understand. 

// i will also convert all the input into a 'TreeNode' class while i am doing this pass down the input. 
// i can add some methods later if i wish. 

// i will also get the root of the tree while i am doing this... 
$rootNode = new TreeNode(array_shift($ar)); 

$treeNodeList = array(); 
foreach($ar as $node) { 
    if (is_array($node->abh)) { // generate duplicate nodes 
     foreach($node->abh as $parentName) { 
      $node->abh = $parentName; // make it an ordinary node 
      $treeNodeList[] = new TreeNode($node); 
     } 
     continue; 
    } 
    $treeNodeList[] = new TreeNode($node); 
} 

// var_dump($ar, $rootNode, $treeNodeList); 

// Ok, we now have a node list in the appropriate order - let us build the tree 

/** 
* This is a 'multiway' tree .i.e. there can be any number of 'child' nodes 
*         for any parent 
* Usual rules: 
* o The parent MUST be in the tree already. 
* o Children are added, by searching from the root of the tree, in this version 
* 
*/ 

// the output will be here 
$theTree = array($rootNode->name => $rootNode); 

foreach ($treeNodeList as $childNode) { // add it 
    $inserted = insertNode($rootNode, $childNode); 
    if (!$inserted) { 
     var_dump('Unable to insert:', $childNode, ' in tree:', $rootNode); 
     die('i am here: '. __FILE__.__LINE__); 
    } 
} 

// show the tree 
echo '<pre>'; 
    print_r($theTree); 
echo '</pre>'; 

exit; 
// --------- end of processing ------------- 

/** 
* Insert the node in the tree 
* 
* @param TreeNode $parent 
* @param TreeNode $newChild 
*/ 
function insertNode(TreeNode &$parent, TreeNode $newChild) { 
    if ($newChild->abh === $parent->name) { // add it to the current parent 
     $parent->children[$newChild->name] = $newChild; // add child 
     return true; 
    } 

    // check the children 
    foreach($parent->children as $newParent) { 
     if (insertNode($newParent, $newChild)) { 
      return true; 
     } 
    } 
    return false; // unable to insert child in the tree 
} 

// ----------------------------------------------------------------------- 
/** 
* treeNode: (Data and Relationships) 
* nodeId:   'name' 
* nodeData:   'otherstuff' 
* nodeParentList: 'abh' - may be a list of parents. 
*       Note: In this version of the code: All the parents 
*        MUST be in the tree already. 
* children:   array of treeNode - recursive structure 
*/ 

// i will make the properties all public to make it easier to debug. 

class TreeNode { 
    public $name = ''; 
    public $otherstuff = array(); 
    public $abh = ''; 
    public $children = array(); // list of child nodes 

    public function __construct(stdClass $node) 
    { 
     $this->name = $node->name; 
     $this->otherstuff = $node->otherstuff; 
     $this->abh = $node->abh; 
    } 
} // class end -------------------------- 
+0

정말 고마워요! 내가 원했던 거지. – UnskilledFreak

관련 문제