Путь к каталогу рекурсивного массива с отношением детей - PullRequest
1 голос
/ 29 апреля 2020

Я хочу разбить путь к каталогу в рекурсивный массив с дочерними элементами, но сохранить каталоги уникальными.

Допустим, у нас есть следующий ввод:

$paths = [
    'parent/first child',
    'parent/second',
    'parent/second/with-another-children',
    'parent/third/another children',
    'parent/last children'
];

foreach($paths as $path){
    $folders = explode('/', $path);

    //$traverse($folders);
}

Ожидаемый вывод

[
    'directory_name' => 'parent',
    'children' => [
        [
            'directory_name' => 'first child',
            'children' => []
        ],
        [
            'directory_name' => 'second',
            'children' => [
                'directory_name' => 'with-another-children',
                'children' => []
            ]
        ],
        [
            'directory_name' => 'third',
            'children' => [
                'directory_name' => 'another children',
                'children' => []
            ]
        ],
        [
            'directory_name' => 'last children',
            'children' => []
        ],
    ]
];

Я получил этот массив путей из папки HTML. Сначала мне нужно создать каталоги (в БД, а не в файловой системе), а затем загружать файлы (все в одной папке), но хранить идентификатор каталога, где должен отображаться файл. Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Вам не нужно использовать рекурсивную функцию для построения структуры, и если вы используете массив с ключами, с ним становится намного проще работать, так как вам не нужно искать в массивах записи с определенной directory_name:

$paths = [
    'parent/first child',
    'parent/second',
    'parent/second/with-another-children',
    'parent/third/another children',
    'parent/last children'
];

$out = [];

foreach($paths as $path) {
    $parts = explode('/', $path);
    $cur = &$out;
    foreach($parts as $part) {
        if(!key_exists($part, $cur)) {
            $cur[$part] = [ 'children' => []];
        }
        $cur = &$cur[$part]['children'];
    }
    unset($cur);
}

var_dump($out);

Вывод:

array(1) {
  ["parent"]=>
  array(1) {
    ["children"]=>
    array(4) {
      ["first child"]=>
      array(1) {
        ["children"]=>
        array(0) {
        }
      }
      ["second"]=>
      array(1) {
        ["children"]=>
        array(1) {
          ["with-another-children"]=>
          array(1) {
            ["children"]=>
            array(0) {
            }
          }
        }
      }
      ["third"]=>
      array(1) {
        ["children"]=>
        array(1) {
          ["another children"]=>
          array(1) {
            ["children"]=>
            array(0) {
            }
          }
        }
      }
      ["last children"]=>
      array(1) {
        ["children"]=>
        array(0) {
        }
      }
    }
  }
}
0 голосов
/ 29 апреля 2020

Вы действительно можете использовать рекурсивную функцию с этим шаблоном:

  • Просмотрите дочерние элементы root, если существует первый каталог. Он не создает его
  • Затем добавьте все оставшиеся каталоги к дочерним элементам этого потомка

Я добавил первый пустой элемент для представления root, потому что я не уверен, что все пути начнутся в parent

Обратите внимание на &, чтобы сохранить изменения в дереве вне функции:

$tree = array('directory_name' => '' /* root */, 'children' => array());
foreach($paths as $path){
    $folders = explode('/', $path);

    addFoldersToTree($tree, $folders);
}
print_r($tree);


function addFoldersToTree(&$tree, $folders)
{
    if( count($folders) == 0 )
    {
        // no more path to add, end
        return ;
    }
    else
    {
        foreach($tree['children'] as &$child) 
        {
            if($child['directory_name'] == $folders[0])
            {
                // first directory already exists, add the rest of the path to this child
                addFoldersToTree($child, array_slice($folders, 1));
                return ;
            }
        }

        // child doesnn't exists yet, create it ...
        $new_child = array(
            'directory_name' => $folders[0],
            'children' => array() 
        );
        addFoldersToTree($new_child, array_slice($folders, 1)); //... and append the rest of the path to it
        $tree['children'][] = $new_child ;
    }
}
...