J'ai des arbres comme celui-ci:La façon la plus élégante de marcher arbres en PHP
$tree = array("A", array(
array("B", 1),
array("C", 2),
array("D",
array("E",
array("F")),
array("G")),
array("H", 3)));
Chaque noeud est un tableau, le type de noeud est le premier élément et d'autres éléments sont les arguments de noeud (ils peuvent être la liste d'autres noeuds, un seul noeud, une certaine valeur etc., le noeud ne peut pas avoir d'argument, un argument ou plusieurs arguments). D'après vous, quelle est la façon la plus élégante de marcher sur ces types d'arbres, selon vous?
je suis venu avec deux possibilités:
1) en utilisant la déclaration 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;
}
}
objet 2) avec la méthode pour chaque type de noeud
/*
* + 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) { /*...*/ }
}
Ou proposez-vous encore plus élégant façon de marcher les arbres? J'ai aussi considéré les nœuds comme des objets et à la place des marcheurs d'arbres séparés, chaque nœud aurait des méthodes pour se promener à l'intérieur. Cependant, je pense que cela rendra le code plus difficile à maintenir, car certaines parties du code des marcheurs seront placées dans des endroits différents et il sera plus difficile d'utiliser le même code pour plusieurs nœuds.
Le problème est tous les nœuds ne seront pas traités de la même. Il y aura toujours besoin de commutateur ou de quelque chose. Ou est-ce que je manque quelque chose? –
@Jak La traversée elle-même est indépendante de ce que les structures de données, tant qu'elles sont itérables. Si vous voulez traiter les éléments différemment, oui, vous aurez toujours besoin d'une instruction switch ou vous pouvez utiliser des objets à la place des tableaux et tirer parti de la répartition dynamique. – Artefacto
Comme je l'ai écrit dans ma question, j'ai considéré les objets et je pense qu'ils seraient plus de mal que de bien. –