2012-01-12 63 views
24

我環顧了網絡,並沒有完全找到我要找的東西。我有一個包含'id'和'parent_id'的每個元素的平面數組。每個元素只有一個父親,但可能有多個孩子。如果parent_id = 0,則它被視爲根級別項目。我試圖讓我的平板數組成一棵樹。我發現的其他樣品只能將該元素複製到父級,但原始樣式仍然存在。從PHP中的平面陣列構建樹

EDIT

起始陣列的每個元件由一個單獨的XML文件中讀取。如果父文件沒有父文件,則文件本身將具有「0」作爲parent_id的值。鑰匙實際上是字符串。

我很抱歉,以前的困惑。希望這是更清晰:

/EDIT

我的出發陣列:

 
Array 
(
    [_319_] => Array 
     (
      [id] => 0 
      [parent_id] => 0 
     ) 

    [_320_] => Array 
     (
      [id] => _320_ 
      [parent_id] => 0 
     ) 

    [_321_] => Array 
     (
      [id] => _321_ 
      [parent_id] => _320_ 
     ) 

    [_322_] => Array 
     (
      [id] => _322_ 
      [parent_id] => _321_ 
     ) 

    [_323_] => Array 
     (
      [id] => _323_ 
      [parent_id] => 0 
     ) 

    [_324_] => Array 
     (
      [id] => _324_ 
      [parent_id] => _323_ 
     ) 

    [_325_] => Array 
     (
      [id] => _325_ 
      [parent_id] => _320_ 
     ) 
)

結果數組的樹由後:

 
Array 
(
    [_319_] => Array 
     (
      [id] => _319_ 
      [parent_id] => 0 
     ) 

    [_320_] => Array 
     (
      [id] => _320_ 
      [parent_id] => 0 
      [children] => Array 
       (
        [_321_] => Array 
         (
          [id] => _321_ 
          [parent_id] => _320_ 
          [children] => Array 
           (
            [_322_] => Array 
             (
              [id] => _322_ 
              [parent_id] => _321_ 
             ) 
           ) 
         ) 
        [_325_] => Array 
         (
          [id] => _325_ 
          [parent_id] => _320_ 
         ) 
       ) 
    [_323_] => Array 
     (
      [id] => _323_ 
      [parent_id] => 0 
      [children] => Array 
       (
        [_324_] => Array 
         (
          [id] => _324_ 
          [parent_id] => _323_ 
         ) 
       ) 
     ) 

任何幫助/指導不勝感激!

某些代碼我迄今爲止:

 

     function buildTree(array &$elements, $parentId = 0) { 
     $branch = array(); 

     foreach ($elements as $element) { 
      if ($element['parent_id'] == $parentId) { 
       $children = $this->buildTree($elements, $element['id']); 
       if ($children) { 
        $element['children'] = $children; 
       } 
       $branch[] = $element; 
      } 
     } 

     return $branch; 
    } 

+1

我很困惑。你只是要求我們編寫代碼,並將你的第一個數組中的數據吐出來? – MetalFrog 2012-01-12 18:30:23

+0

是啊......這裏有什麼問題? – 2012-01-12 18:32:00

+0

總之,我想是的。我在這裏查看了各種其他的例子,在其他博客/論壇上。但是當我嘗試過它們時,它們不起作用。 – DSkinner 2012-01-12 18:33:12

回答

38

你忘了在那裏的兄弟的unset()

function buildTree(array &$elements, $parentId = 0) { 
    $branch = array(); 

    foreach ($elements as $element) { 
     if ($element['parent_id'] == $parentId) { 
      $children = buildTree($elements, $element['id']); 
      if ($children) { 
       $element['children'] = $children; 
      } 
      $branch[$element['id']] = $element; 
      unset($elements[$element['id']]); 
     } 
    } 
    return $branch; 
} 
+3

此解決方案可能無法在某些情況下正確構建樹(即$ arr = array(array('id'=> 1,'parentid'=> 0),array('id'=> 10,'parentid'=> 2),array('id'=> 2,'parentid '=> 0),array('id'=> 3,'parentid'=> 10),array('id'=> 4,'parentid'=> 0),array('id'=> 11,''數組'('id'=> 5,'parentid'=> 0),數組('id'=> 6,'pa​​rentid'=> 1) 'parentid'=> 11),array('id'=> 9,'parentid'=> 0),array('id'=> 7,'parentid'=> 0),);)我會建議: http://stackoverflow.com/questions/4196157/create-array-tree-from-array-list(亞瑟的修改解決方案) – danicotra 2013-03-22 20:22:51

+1

它不拯救沒有孩子的第一父母。 – mrded 2015-01-06 20:01:11

+0

@Freedom_Ben謝謝我試試:) – n0nag0n 2015-11-11 00:09:15

3

我可以看到的邏輯,此保存在結果:

Array 
(
    [0] => Array 
     (
      [id] => 0 
      [parent_id] => 0 
     ) 

    [1] => Array 
     (
      [id] => 1 
      [parent_id] => 0 
     ) 

IMHO,是PARENT_ID = O,不應該[1 ]在這裏是[0]的孩子嗎?

無論如何,救援引用:

$tree = array(); 
foreach($inputarray as $item){ 
    if(!isset($tree[$item['id']])) $tree[$item['id']] = array(); 
    $tree[$item['id']] = array_merge($tree[$item['id']],$item); 
    if(!isset($tree[$item['parent_id']])) $tree[$item['parent_id']] = array(); 
    if(!isset($tree[$item['parent_id']]['children'])) $tree[$item['parent_id']]['children'] = array(); 
    $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; 
} 
$result = $tree[0]['children']; 
unset($tree); 
print_r($result); 

因爲你們虐待0作爲一個現有ID既是一個「神奇」號作爲根,而且,我們現在已經在id = 0分支遞歸。在$tree[$item['parent_id']]['children'][] = &$tree[$item['id']];之前添加if($item['parent_id']!=$item['id'])可以防止這種情況發生,但這並不美觀。

+0

+1 becouse recusion使我的情況下允許的內存大小用盡。在我的情況下,有54個對象,這足以滿足我的記憶。 – bumerang 2016-05-06 13:17:36

2

它可以構建源陣列稍有不同,你可以使用此功能(PARENT_ID,身份證,職稱):

$q = mysql_query("SELECT id, parent_id, name FROM categories"); 
while ($r = mysql_fetch_row($q)) { 
    $names[$r[0]] = $r[2]; 
    $children[$r[0]][] = $r[1]; 
} 

function render_select($root=0, $level=-1) { 
    global $names, $children; 
    if ($root != 0) 
    echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>'; 
    foreach ($children[$root] as $child) 
    render_select($child, $level+1); 
} 

echo '<select>'; 
render_select(); 
echo '</select>'; 
  1. More efficient hierarchy system
0

你想尋找在存儲和在MySQL中加載分層數據,因爲我應該解決一些問題。我假設第一個數組代表直接從數據庫中獲取的數據?

它看起來像你試圖使用鄰接模型來組織你的數據到層次結構。還有其他方法可以使用嵌套來實現此目的。如果你沒有從數據庫中獲取這些數據,那麼這可能不是那麼有用。

這個鏈接應該幫助你:http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

+0

雖然它正確地說明了使用鄰接模型作爲嵌套集合1,但實際上(至少在我的經驗中),嵌套集合模型對於突變而言是昂貴的(平均一半的表格需要更新! )爲任何實際數據。如果數據相對陳舊(即:很少發生變化),那麼它是可行的,但通常情況並非如此。 – Wrikken 2012-01-12 19:00:59

+0

@Wrikken是的它取決於數據如何使用/更新。對於類別來說很好,但對於有很多修改的數據來說根本不可行。忘了提及,謝​​謝:) – 2012-01-12 19:28:52

5

這個工作對我來說:

$index=array(); 
$tree=array(); 
foreach ($ori as $key=>$var) { 
    $var=array_shift($ori); 
    if ($var['id']==0) $var['id']=$key; 
    if ((string)$var['parent_id']==='0') { 
    $tree[$key]=$var; 
    $index[$key]=&$tree[$key]; 
    } else if (isset($index[$var['parent_id']])) { 
    if (!isset($index[$var['parent_id']]['children'])) $index[$var['parent_id']]['children']=array(); 
    $index[$var['parent_id']]['children'][$key]=$var; 
    $index[$key]=&$index[$var['parent_id']]['children'][$key]; 
    } else { 
    array_push($ori,$var); 
    } 
} 
unset($index); 
print_r($tree); 
+0

我喜歡索引的使用。輝煌。 – 2013-02-19 11:17:10

0

這裏是我的解決方案,工作理想情況下,如果我們假設頂層PARENT_ID = 0:

function MakeTree($arr){ 
    $parents_arr=array(); 
    foreach ($arr as $key => $value) { 
     $parents_arr[$value['pid']][$value['id']]=$value; 
    } 
    $tree=$parents_arr['0']; 
    $this->createTree($tree, $parents_arr); 
    return $tree; 
} 
function createTree(&$tree, $parents_arr){ 
    foreach ($tree as $key => $value) { 
     if(!isset($value['children'])) { 
      $tree[$key]['children']=array(); 
     } 
     if(array_key_exists($key, $parents_arr)){ 
      $tree[$key]['children']=$parents_arr[$key]; 
      $this->createTree($tree[$key]['children'], $parents_arr); 
     } 
    } 
} 
2

儘管這是一個老問題,我在這裏我會後我的回答:

/* assuming top level pid = 0 */ 
$rows = array (
    array ('id' => 1, 'pid' => 0), 
    /* ... */ 
); 

/* make id become array key */ 
$rows = array_column ($rows, null, 'id'); 

foreach ($rows as $key => $val) { 
    if ($val ['pid']) { 
     if (isset ($rows [$val ['pid']])) { 
      $rows [$val ['pid']]['children'][] = &$rows [$key]; 
     } 
    } 
} 

foreach ($rows as $key => $val) { 
    if ($val ['pid']) unset ($rows [$key]); 
} 

array_column是PHP 5.5,但你可以輕鬆製作。

22

然而,正如mrded指出的,ImmortalFirefly的解決方案正在發揮作用,它不會拯救沒有孩子的第一父母。我已編輯功能來解決此問題:

function buildTree(array &$elements, $parentId = 0) { 

    $branch = array(); 

    foreach ($elements as &$element) { 

     if ($element['parent_id'] == $parentId) { 
      $children = buildTree($elements, $element['id']); 
      if ($children) { 
       $element['children'] = $children; 
      } 
      $branch[$element['id']] = $element; 
      unset($element); 
     } 
    } 
    return $branch; 
} 
+0

你剛剛救了我6個。我的老闆正打算把我打死。唷。非常感謝。 – 2015-11-18 22:02:20

+0

謝謝!正是我需要的! – maxpower9000 2016-01-27 11:15:31

0

這是我的解決方案,複製和優化其他解決方案。

function buildTree(array &$elements, $parentId = 0) { 
    $branch = array(); 
    foreach ($elements as $key => $element) { 
     if ($element['parent_id'] == $parentId) { 
      $children = $this->buildTree($elements, $key); 
      if ($children) { 
       $element['children'] = $children; 
      } 
      $branch[$key] = $element; 
      unset($elements[$key]); 
     } 
    } 
    return $branch; 
} 
0

乾淨,短而且沒有壓載物。數組到樹的陣列:

class Mother { 
    private $root; 
    public function treeInit($array) 
    { 
     $this->root = new Child(); 
     foreach($array as $value){ 
      $this->root->treeClimb(array_reverse($value)); 
     } 
     return $this->root; 
    } 
} 

class Child { 
    private $children = []; 
    public function treeClimb($arr) 
    { 
     if(count($arr) > 0) { 
      $childTmp = array_pop($arr); 
      if(!key_exists($childTmp,$this->children)) 
      { 
       $this->children[$childTmp] = new Child(); 
      } 
     $this->children[$childTmp]->treeClimb($arr); 
     } 
    } 
} 

$array = array(array('obst','banae','krumm','gelb'), 
        array('obst','beere','him'), 
        array('obst','beere','brom'), 
        array('obst','banae','gerade'), 
        array('veg','carot','gerade')); 

$obj = new Mother(); 
var_dump($obj->treeInit($array));