2013-02-19 2 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 
) 
) 

я хочу, чтобы это было превращено в многомерном массиве таким образом, что непосредственные элементы с глубиной выше предыдущего элемента войдет в предыдущий элемент с ключом «дети». например:

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

Я в настоящее время в моем конце остроумия пытается прийти вверх с некоторым array_push подхода с использованием пара, если условия в цикле, но, к сожалению, не принесло ... – VeeBee

+0

Там нет логической связи в коде здесь между родитель и ребенок. Единственное, что вы знаете с помощью вашего начального ввода, - это уровни глубины. Можно было бы создать дерево, основанное исключительно на глубине, но похоже, что вы гнездились как термины. TUBE, LCD и PLASMA являются детьми ТЕЛЕВИЗОРОВ, но ПОРТАТИВНАЯ ЭЛЕКТРОНИКА не имеет детей. Как код знает отношения? – tmsimont

+0

oops, извините, я пропустил это: «Я хочу, чтобы он преобразовывался в многомерный массив, так что непосредственные элементы с глубиной, превышающей предыдущий элемент, войдут внутрь предыдущего элемента с ключом« дети »« – tmsimont

ответ

1

Вот моя трещина на это ... Использует цикл Еогеаспа и массив указателей, чтобы следить за связку различных указателей родителей.

$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

+0

без проблем! Мне нравятся логические головоломки – tmsimont

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; 
} 

Edit: Как указано в коментарии предыдущей функции Wasnt работает должным образом, это должно быть в порядке, по-прежнему имеет побочный эффект уничтожения исходного массива.

+0

выглядит так: ПОРТАТИВНАЯ ЭЛЕКТРОНИКА не получает обратно на верхний уровень – tmsimont

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

+0

Я пробовал это, но не дал желаемого результата. – VeeBee

Смежные вопросы