我有这样一个树:走树木PHP
$tree = array("A", array(
array("B", 1),
array("C", 2),
array("D",
array("E",
array("F")),
array("G")),
array("H", 3)));
每个节点是一个数组,节点的类型是它的第一个元素和其他元素节点的参数(也可以是列表其他节点,单个节点,一些值等;节点可以没有参数,一个参数或多个参数)。
您认为最优雅的方式来走这些类型的树木?
我想出了两种可能性:
1)使用switch
声明
/*
* + 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) { /*...*/ }
}
还是你建议更优雅行走树的方式?
我也认为节点是对象,而不是独立的树步行者,每个节点都有内部散步的方法。不过,我认为这会让代码难以维护,因为步行者代码的一部分将被放置在不同的位置,并且使用相同的代码更难以用于更多的节点。
的问题是所有节点都不会被处理一样。仍然需要开关或其他东西。或者我错过了什么? – 2010-06-22 20:56:37
@Jak遍历本身独立于数据结构,只要它们是可迭代的。如果你想对待不同的元素,是的,你仍然需要一个switch语句,或者你可以使用对象而不是数组,并利用动态分派。 – Artefacto 2010-06-22 22:16:54
正如我在我的问题中写的那样,我考虑过对象,我认为它们会比弊端更坏。 – 2010-06-23 13:48:19