PHP中最优雅的树木行走方式
我有这样的树:PHP中最优雅的树木行走方式,php,tree,Php,Tree,我有这样的树: $tree = array("A", array( array("B", 1), array("C", 2), array("D", array("E", array("F")), array("G")), array("H", 3))); 每个节点都是一个数组,节点的类型是它的第
$tree = array("A", array(
array("B", 1),
array("C", 2),
array("D",
array("E",
array("F")),
array("G")),
array("H", 3)));
每个节点都是一个数组,节点的类型是它的第一个元素,其他元素是节点的参数(它们可以是其他节点的列表、单个节点、某些值等;节点可以没有参数、一个参数或多个参数)
你认为走这类树最优雅的方式是什么
我提出了两种可能性:
1) 使用开关
语句
/*
* + shorter
* + fall-througs (easy way to handle more nodes with same code)
*
* - worse readability
*/
function my_tree_walker($tree)
{
switch ($tree[0]) {
case 'A':
list($_, $subnodes) = $tree;
$ret = '';
foreach ($subnodes as $subnode) {
$ret .= my_tree_walker($subnode);
}
return $ret;
break;
case 'B': /*...*/ break;
case 'C': /*...*/ break;
case 'D': /*...*/ break;
case 'E': /*...*/ break;
case 'F': /*...*/ break;
case 'G': /*...*/ break;
case 'H': /*...*/ break;
}
}
2) 对象,并为每个节点类型指定方法
/*
* + better readability
* + more declarative
*
* - longer
* - `new static` is PHP >=5.3 only
*/
abstract class TreeWalker
{
protected function __construct(){}
final protected function walk($node)
{
$nodetype = array_shift($node);
return call_user_func_array(array($this, 'walk' . $nodetype), $node);
}
public static function w($tree)
{
$instance = new static;
return $instance->walk($tree);
}
}
final class MyTreeWalker extends TreeWalker
{
protected function __construct()
{
// initialize
}
private function walkA($subnodes)
{
$ret = '';
foreach ($subnodes as $subnode) {
$ret .= $this->walk($subnode);
}
return $ret;
}
private function walkB($n) { /*...*/ }
private function walkC($n) { /*...*/ }
private function walkD($subnode) { /*...*/ }
private function walkE() { /*...*/ }
private function walkF() { /*...*/ }
private function walkG() { /*...*/ }
private function walkH($n) { /*...*/ }
}
或者你建议更优雅的方式行走树木
我还认为节点是对象,而不是单独的树漫游器,每个节点都有内部漫游的方法。然而,我认为这将使代码更难维护,因为walkers的部分代码将被放置在不同的位置,并且对于更多的节点使用相同的代码将更加困难。请看:
- 我认为简单就是优雅
不需要重新发明轮子!PHP附带了一些功能,可以为您完成所有工作
有几个要检查的是和我结合了这两种方式并创建了DSL:
A ($subnodes) {
$ret = '';
foreach ($subnodes as $subnode) {
$ret .= WALK($subnode);
}
return $ret;
}
B ($n) { /*...*/ }
C ($n) { /*...*/ }
D ($subnode) { /*...*/ }
E () { /*...*/ }
F () { /*...*/ }
G () { /*...*/ }
H ($n) { /*...*/ }
这已转换为PHP。我建议使用以下库: TreeWalker是一个简单的小型库,它可以帮助您更快地在PHP中操作结构
- getdiff()-获取json差异
- walker()-编辑json(递归)
- structMerge()-连接两个结构
- createDynamicallyObjects()-通过动态键创建嵌套结构
- getDynamicallyValue()-动态获取结构属性
- setDynamicallyValue()-动态访问结构属性以设置值
function deep_cetegories($categories){
foreach($categories as $category)
{
print_r((json_encode($category['category_name'])));
if(isset($category['children']))
{
deep_cetegories($category['children']);
}
}
}
问题是,并非所有节点都会得到相同的处理。仍然需要开关之类的东西。还是我遗漏了什么?@Jak遍历本身与数据结构无关,只要它们是可写的。如果您想以不同的方式对待元素,是的,您仍然需要一个switch语句,或者您可以使用对象而不是数组,并利用动态分派。正如我在问题中所写的,我考虑了对象,我认为它们弊大于利。问题是所有节点的处理方式都不相同。仍然需要开关之类的东西。或者我遗漏了什么?你能提供一个你希望对节点做什么的例子,让我们更好地了解你想要完成什么吗?我正在尝试在我的PEG生成器中重构树漫游器(比如:,以及以下以“g”开头的方法)。我想将它们分开(单独的类/函数),并使用相同的语言结构。