1

我有一個PHP對象的一維數組。每個對象都有兩個屬性,一個屬性是對象的唯一ID,另一個是數組中其父對象的唯一ID。例如:使用單維數組中的數據創建多維數組

array(3) { 
    [0]=> 
    object(stdClass)#1 (2) { 
    ["ID"]=> 
    int(1) 
    ["parentID"]=> 
    int(0) 
    } 
    [1]=> 
    object(stdClass)#2 (2) { 
    ["ID"]=> 
    int(3) 
    ["parentID"]=> 
    int(2) 
    } 
    [2]=> 
    object(stdClass)#3 (2) { 
    ["ID"]=> 
    int(2) 
    ["parentID"]=> 
    int(1) 
    } 
} 

我需要將此一維數組轉換爲多維數組。我已經採取了一些措施,但我無法找到一個方法來完成沒有每個級別的嵌套循環。該算法需要能夠適應假設無限級別的嵌套。我試過使用一些遞歸技術,但我從來沒有得到它很正確。

要增加一點複雜性,我得到的數組中的對象並不總是按照一個合理的順序。我試圖在上面的例子中複製這個;你會注意到ID爲3的對象在ID爲2的對象之前進入數組。因此它們也可能是一個排序算法。

理想上面的例子會變成這樣的:

Array 
(
    [0] => Array 
     (
      [ID] => 1 
      [parentID] => 0 
      [0] => Array 
       (
        [ID] => 2 
        [parentID] => 1 
        [0] => Array 
         (
          [ID] => 3 
          [parentID] => 2 
         ) 

       ) 

     ) 

) 
+0

您的示例數據中有父/子遞歸。節點3的父節點是2,節點2的父節點是3.你有打字錯誤嗎? – 2009-11-10 17:48:53

+0

我做到了,謝謝你的發現。它現在已經修復。 – macinjosh 2009-11-10 17:56:54

+0

這裏的僞代碼答案是否合適,或者您是否正在尋找PhP響應? – aperkins 2009-11-10 18:00:11

回答

3

試試這個算法:

// sort objects by parentID 
function cmpNodes($a, $b) { 
    return $a->parentID - $b->parentID; 
} 
usort($objects, 'cmpNodes'); 

// define first node as root of tree 
$tree = (array) array_shift($objects); 
// lookup table for direct jumps 
$idTable = array($tree['ID'] => &$tree); 
foreach ($objects as $object) { 
    $node = (array) $object; 
    // test if parent node exists 
    if (!isset($idTable[$node['parentID']])) { 
     // Error: parent node does not exist 
     break; 
    } 
    // append new node to the parent node 
    $idTable[$node['parentID']][] = $node; 
    // set a reference in the lookup table to the new node 
    $idTable[$node['ID']] = &$idTable[$node['parentID']][count($idTable[$node['parentID']])-3]; 
} 
// unset($idTable); 
var_dump($tree); 

我用的ID直接跳轉到該節點查找表($idtable) 。

1

所以,就像一個前兆 - 我不知道PHP,真的。我主要是一個c風格的語言開發人員(aka c,Objective c和Java)。因此,一些本可能會更困難PHP做的,但這裏是我的嘗試將使:

//the original input array 
oldArray; 
//the output array 
array[] newArray = new array[]; 

foreach (element : oldArray) { 
    //if the element is at the top, put it at the top of the array 
    if (element.parentId == 0) { 
     newArray.add(element); 
    } else { 
     //otherwise, find it's parent and put it in the child array of the parent 
     for (potentialParent : oldArray) { 
      if (potentialParent.id = element.parentId) { 
       potentialParent.array.add(element); 
       break; 
      } 
     } 
    } 
} 

有兩點要注意:我假設你周圍的一切傳遞的指針。如果你正在製作這些物體的副本,這會更困難,但並非不可能。我也假設你可以動態改變數組的大小。再一次,我不太瞭解php - 如果你不能這麼做,那麼你需要一種程序化的方式來做到這一點。在Java中我會使用列表類型,或者只是複製數組並重新設置它。

這個算法的關鍵在於將孩子放在他們的父母之下 - 無論他們在哪裏 - 一次通過。這意味着,無論順序如何,層次結構都將在單次傳遞中創建。如果你需要身邊,你在你的例子顯示父包裝數組,你可以簡單地添加像這樣的代碼的末尾:

finalArray = new array[]; 
finalArray[0] = newArray; 

希望這有助於。