2013-02-19 101 views
1

假設我有此數組:轉換一個維陣列成多維數組

Array 
(
    [0] => Array 
    (
    [name] => ELECTRONICS 
    [depth] => 0 
) 

    [1] => Array 
    (
    [name] => TELEVISIONS 
    [depth] => 1 
) 

    [2] => Array 
    (
    [name] => TUBE 
    [depth] => 2 
) 

    [3] => Array 
    (
    [name] => LCD 
    [depth] => 2 
) 

    [4] => Array 
    (
    [name] => PLASMA 
    [depth] => 2 
) 

    [5] => Array 
    (
    [name] => PORTABLE ELECTRONICS 
    [depth] => 1 
) 
) 

我希望它被轉換成一個多維陣列,使得以比以前的元件更高的深度立即元件將使用關鍵字「children」進入前一個元素。像這樣:

Array 
(
    [0] => Array 
    (
    [name] => ELECTRONICS 
    [depth] => 0 
    [children] => Array 
    (
     [0] => Array 
     (
     [name] => TELEVISIONS 
     [depth] => 1 
     [children] => Array 
     (
      [0] => Array 
      (
      [name] => TUBE 
      [depth] => 2 
     ) 

      [1] => Array 
      (
      [name] => LCD 
      [depth] => 2 
     ) 

      [2] => Array 
      (
      [name] => PLASMA 
      [depth] => 2 
     ) 
     ) 
    ) 

     [1] => Array 
     (
     [name] => PORTABLE ELECTRONICS 
     [depth] => 1 
    ) 
    ) 
) 
) 

非常感謝您的幫助。謝謝;)

+0

目前我在我束手無策嘗試使用一對夫婦如果在一個for循環但遺憾的是無濟於事的條件... – VeeBee 2013-02-19 15:58:39

+0

有這裏的之間的代碼沒有邏輯連接來-了一些array_push方法父母和孩子。您在初始輸入中唯一知道的是深度級別。人們可能會根據深度創建一棵樹,但看起來像嵌套像條款一樣。 TUBE,LCD和PLASMA是電視的孩子,但PORTABLE ELECTRONICS沒有孩子。代碼如何知道這種關係? – tmsimont 2013-02-19 15:59:57

+0

哎呀,對不起,我錯過了這個:「我希望它被轉換成一個多維數組,使深度高於前一個元素的直接元素將進入前一個元素的內部,使用鍵」children「」 – tmsimont 2013-02-19 16:00:52

回答

1

這裏是我的裂紋吧...使用foreach循環和指針數組保持了一堆軌道不同的父指針。

$multi_dimensional = array(); 
$last_depth = 0; 
$parent = &$multi_dimensional; 
$parents[$last_depth] = &$parent; 


foreach ($start as $idx => $data) { 
    // same/increasing depth 
    if ($last_depth <= $data['depth']) { 
    $parent['children'][] = $data; 
    } 

    // increasing depth 
    if ($last_depth < $data['depth']) { 
    $parents[$last_depth] = &$parent; 
    } 

    // decreasing depth 
    if ($last_depth > $data['depth']) { 
    $parent = &$parents[$data['depth']-1]; 
    $parent['children'][] = $data; 
    } 

    // look ahead and prepare parent in increasing 
    if (isset($start[$idx+1]) && $start[$idx+1]['depth'] > $data['depth']) { 
    $last_insert_idx = count($parent['children'])-1; 
    $parent = &$parent['children'][$last_insert_idx]; 
    } 
    $last_depth = $data['depth']; 
} 

// initial values are in child "children" array 
$result = $multi_dimensional['children']; 
+0

cernunnos的遞歸解決方案也可以工作,但由於它是非遞歸的,所以這個方法更高效。感謝你的付出! – VeeBee 2013-02-19 23:58:43

+0

沒問題!我喜歡這樣的邏輯謎題 – tmsimont 2013-02-20 00:10:51

1

我道歉的名稱和它的遞歸性質。另外,請注意,這個功能將「消滅」,如果你想保持它

function multiDimensionate(&$arr, $currentLevel = 0) { 
    $root = array(); 

    foreach ($arr as &$elem){ 
    if ($elem["depth"] == $currentLevel) { 
     $root[] = $elem; 
     unset($elem); 
    } else if ($elem["depth"] == $currentLevel + 1) { 
     $root[count($root)-1]["children"] = multiDimensionate($arr,$elem["depth"]);  
    } 
    } 

    return $root; 
} 

編輯您的原始數組所以使用克隆:正如評析指出,先前的功能wasnt正常工作,這應該沒問題,仍然有破壞原始數組的副作用。

+0

看起來像PORTABLE ELECTRONICS沒有得到提升備份到頂層 – tmsimont 2013-02-19 16:34:15

2

這是一個棘手的問題。我不知道這是否是實現這一目標的最優化的方式,但它的工作原理:

function flat_to_tree($array, $depth = 0) 
{ 
    $out = array(); 
    $inCurrentDepth = true; 

    foreach ($array as $key => $value) { 
    if ($value['depth'] < $depth) { 
     return $out; 
    } 

    if ($value['depth'] === $depth) { 
     $inCurrentDepth = true; 
     $out[] = $value; 
    } 

    if ($inCurrentDepth && $value['depth'] > $depth) { 
     $inCurrentDepth = false; 
     $out[$key - 1]['children'] = flat_to_tree(array_slice($array, $key), $value['depth']); 
    } 
    } 

    return $out; 
} 
+0

很好地使用遞歸和php本地功能。我去了不太令人興奮的foreach循環方法 – tmsimont 2013-02-19 17:08:43

+0

我試過這個,但它沒有輸出所需的結果。 – VeeBee 2013-02-19 23:54:40