将路径数组转换为树

  • 本文关键字:转换 数组 路径 php
  • 更新时间 :
  • 英文 :



我想转换一个路径名数组,如

$paths = ["foo/bar/lorem", "foo/bar/ipsum", "foo/dolor"];

转换为树阵列。上面例子的匹配树数组是:

$tree = [
[
"name" => "foo",
"children" => [
[
"name" => "bar",
"children" => [
[
"name" => "lorem",
"children" => []
],
[
"name" => "ipsum",
"children" => []
]
]
],
[
"name" => "dolor",
"children" => []
]
]
]
];

我知道,这不会那么难,但PHP处理通过参考传递与通过价值传递的问题让我很挣扎。

谢谢。

编辑:在我看来,这不是重复的,就像你提到的线程中一样,有给定的父ID。

到目前为止我所做的:

private function buildTree()
{
$paths = [
"foo/bar/lorem",
"foo/bar/ipsum",
"foo/dolor",
];
$tree = [];
foreach ($paths as $path) {
$parts = explode("/", $path);
$currentLevel = &$tree;
foreach ($parts as $part) {
$existingPath = $this->findByName($currentLevel, $part);
if ($existingPath) {
$currentLevel = &$existingPath["children"];
} else {
$newPart = [
"name" => $part,
"children" => [],
];
$currentLevel[] = $newPart;
$currentLevel = &$newPart["children"];
}
}
}
return $tree;
}
private function findByName(&$array, $name) {
foreach($array as &$item) {
if (strcmp($item["name"], $name) === 0) {
return $item;
}
}
return false;
}

但这给了我一个机会:

array(1) {
[0]=>
array(2) {
["name"]=>
string(3) "foo"
["children"]=>
array(0) {
}
}
}

这确实奏效了,但只是继续向下投票:

private function buildTree()
{
$paths = [
"foo/bar/lorem",
"foo/bar/ipsum",
"foo/dolor",
];
$tree = [];
foreach ($paths as $path) {
$level = &$tree;
$parts = explode("/", $path);
foreach($parts as $part) {
if (!$this->findByName($level, $part)) {
$level[] = [
"name" => $part,
"children" => []
];
}
$level = &$level[count($level)-1]["children"];
}
}
return $tree;
}
private function findByName(&$array, $name) {
foreach($array as &$item) {
if (strcmp($item["name"], $name) === 0) {
return $item;
}
}
return false;
}

与您所获得的非常相似,但使用一些内置函数来查找要添加到的元素…

function buildTree()
{
$paths = [
"foo/bar/lorem",
"foo/bar/ipsum",
"foo/dolor",
];
$tree = [];
foreach ($paths as $path) {
$parts = explode("/", $path);
$node = &$tree;
foreach ( $parts as $level )   {
$newNode = array_search ($level, array_column($node, "name")??[]);
if ( $newNode === false ) {
$newNode = array_push( $node, [ "name" => $level, "children" => []]) -1;
}
$node = &$node[$newNode]["children"];
}
}
return $tree;
}
print_r(buildTree());

对不起,我迟到了,但这里有另一个使用递归函数的解决方案:

<?php
$paths = array("foo/bar/lorem", "foo/bar/ipsum", "foo/dolor");
$test = [];
foreach($paths as $path){
$splitPath = preg_split('///', $path);
addChild($test, $splitPath);
}
function addChild(&$arr, &$splitPath){
$parent = array_shift($splitPath);
//check for $parent in $test array
$foundParent = 0;
foreach($arr as &$item){
if($item['name'] == $parent){
if(count($splitPath) > 0){addChild($item['children'], $splitPath);}
$foundParent = 1;
}
}
//if not found, add to array
if($foundParent == 0){
$arr[] = array('name' => $parent,'children' => []);
if(count($splitPath) > 0){addChild($arr[count($arr)-1]['children'], $splitPath);}
}
}
print_r($test);
?>

最新更新