2015-08-24 2 views
0

У меня есть массив как это:Создать многомерный массив из плоского массива файла

$arr = array(
    'home.js' => new File(), 
    'view/index.html' => new File(), 
    'src/index.js' => new File(), 
    'src/libs/jquery.js' => new File() 
); 

Теперь я хочу, чтобы преобразовать в структуру, как это:

Array 
(
    [0] => Array 
     (
      [text] => home.js 
     ) 

    [1] => Array 
     (
      [text] => view 
      [children] => Array 
       (
        [0] => Array 
         (
          [text] => index.html 
         ) 

       ) 

     ) 

    [2] => Array 
     (
      [text] => src 
      [children] => Array 
       (
        [0] => Array 
         (
          [text] => index.js 
         ) 

        [1] => Array 
         (
          [text] => libs 
          [children] => Array 
           (
            [0] => Array 
             (
              [text] => jquery.js 
             ) 

           ) 

         ) 

       ) 

     ) 

) 

Я пытался в течение нескольких часов, с помощью StackOverfow отвечает, но я не мог придумать решение, так как все другие вопросы имеют другую настройку.


Edit:

То, что я получил до сих пор с помощью так (не помню точного ответа, хотя):

$out = array(); 
foreach($arr as $path => $file) { 
    $parts = explode('/', trim($path, '/')); 

    applyChain($out, $parts, $file); 
} 

function applyChain(&$arr, $parts, $value) 
{ 
    if (!is_array($parts)) { 
     return; 
    } 

    if (count($parts) == 0) { 
     $arr = $value; 
    } else { 
     array_shift($parts); 
     applyChain($arr[], $parts, $value); 
    } 
} 

print_r($out); 

Я не знаю, как точно это работает, особенно часть applyChain($arr[] ...). Он работает с глубиной, но не с именами файлов. Я получаю следующий вывод:

Array 
(
    [0] => File Object 
     (
     ) 

    [1] => Array 
     (
      [0] => File Object 
       (
       ) 

     ) 

    [2] => Array 
     (
      [0] => File Object 
       (
       ) 

     ) 

    [3] => Array 
     (
      [0] => Array 
       (
        [0] => File Object 
         (
         ) 

       ) 

     ) 

) 
+0

рекурсивной функции и взрывается может помочь. Кстати, что ты пробовал? –

+0

Я отредактировал мой вопрос с тем, что я пробовал до сих пор. –

ответ

1

Там будет решение в несколько строк с использованием explode() и eval(). Но eval() не считается чистым, поэтому давайте попробуем рекурсии:

<?php 

class File { 
} 

$arr = array(
    'home.js' => new File(), 
    'view/index.html' => new File(), 
    'src/index.js' => new File(), 
    'src/libs/jquery.js' => new File() 
); 

function sub($path) { 
     $rv = array(); 
     $parts = explode('/', $path, 2);   // strip off one level 
     $rv['text'] = $parts[0];     // put it into 'text' element 
     if (count($parts)>1)      // is there anything left? 
       $rv['children'] = sub($parts[1]); // do the same for the rest of the path 

     return $rv; 
} 

$new = array(); 
foreach (array_keys($arr) as $file) { 
     $new[] = sub($file); 
} 

var_dump($new); 

?> 

Но, как Питер заметил, это создает раздельные подструктуры, даже если тракты имеют некоторую общую часть (как src/libs/jquery.js и src/libs/melon.js).

С использованием уродливой eval() (который может быть заменен позже), я получил следующий код:

<?php 

class File { 
} 

$arr = array(
    'home.js' => new File(), 
    'view/index.html' => new File(), 
    'src/index.js' => new File(), 
    'src/libs/jquery.js' => new File(), 
    'src/libs/melon.js' => new File(), 
); 

// conversion 
function sub($element) { 
     $rv = array(); 
     foreach (array_keys($element) as $sub) { 
       $part['text'] = $sub; 
       if (is_array($element[$sub])) { 
         $part['children'] = sub($element[$sub]); 
       } 
       $rv[] = $part; 
     } 
     return $rv; 
} 

// create array with path file/folder names as keys 
$new = array(); 
foreach (array_keys($arr) as $row) { 
     $def = '$new["'.preg_replace('&/&', '"]["', $row).'"] = 1;'; 
     eval($def); 
} 

// run 
$new2 = sub($new); 
var_dump($new2); 

?> 

Это выводит

array(3) { 
    [0]=> 
    array(1) { 
    ["text"]=> 
    string(7) "home.js" 
    } 
    [1]=> 
    array(2) { 
    ["text"]=> 
    string(4) "view" 
    ["children"]=> 
    array(1) { 
     [0]=> 
     array(1) { 
     ["text"]=> 
     string(10) "index.html" 
     } 
    } 
    } 
    [2]=> 
    array(2) { 
    ["text"]=> 
    string(3) "src" 
    ["children"]=> 
    array(2) { 
     [0]=> 
     array(1) { 
     ["text"]=> 
     string(8) "index.js" 
     } 
     [1]=> 
     array(2) { 
     ["text"]=> 
     string(4) "libs" 
     ["children"]=> 
     array(2) { 
      [0]=> 
      array(1) { 
      ["text"]=> 
      string(9) "jquery.js" 
      } 
      [1]=> 
      array(1) { 
      ["text"]=> 
      string(8) "melon.js" 
      } 
     } 
     } 
    } 
    } 
} 
+0

Ничего себе, это здорово! Спасибо за это до сих пор. Вы видите легкое решение для нескольких файлов в папке? Например: 'src/libs/jquery.js '=> new File(),' src/libs/melon.js '=> new File()'. Это создало бы целый новый массив «root». Но я предпочел бы иметь его внутри массива children 'libs'. В любом случае, большое спасибо за большой старт. –

+0

Я бы вообще использовал детали как ключи, по-моему, структура текста/детей сложнее, чем нужно. Таким образом, вы получите: '[home.js] => 1, [view] => [index.html] => 1, [src] => [lib] => array ([jquery.js] => 1, [melon.js] => 1) '(это не синтаксис var_dump, но я надеюсь, что вы поняли, что я имею в виду). Затем это может быть выведено в вашу структуру. – syck

+0

Я согласен с вами, что это сложнее, чем нужно. К сожалению, он передан другому инструменту, который нуждается в такой структуре :( –

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