简体   繁体   English

用PHP走树的最优雅方法

[英]The most elegant way to walk trees in PHP

I have trees like this one: 我有这样的树:

$tree = array("A", array(
            array("B", 1),
            array("C", 2),
            array("D",
                array("E",
                    array("F")),
                array("G")),
            array("H", 3)));

Each node is an array, type of node is its first element and other elements are node's arguments (they can be list of other nodes, single node, some value etc.; node can have no argument, one argument or more arguments). 每个节点都是一个数组,节点的类型是其第一个元素,其他元素是节点的参数(它们可以是其他节点的列表,单个节点,某些值等;节点可以没有参数,一个参数或多个参数)。

What do you think is the most elegant way to walk these type of trees? 您认为走这类树的最优雅方式是什么?

I came up with two possibilities: 我想出了两种可能性:

1) using switch statement 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) object with method for each node type 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) { /*...*/ }
}

Or do you suggest even more elegant way of walking trees? 还是您建议使用更优雅的步行树方式?

I also considered nodes being objects and instead of separate tree walkers each node would have methods for walks inside. 我还认为节点是对象,并且每个节点将具有在内部进行遍历的方法,而不是单独的树遍历。 However I think it will make code harder to maintain, because parts of walkers' code will be placed in different locations and it will be harder to use same code for more nodes. 但是我认为这将使代码难以维护,因为步行者的部分代码将放置在不同的位置,并且将相同的代码用于更多的节点将变得更加困难。

I think simplicity is elegant. 我认为简单是优雅的。

No need to reinvent the wheel! 无需重新发明轮子! PHP comes equipped with SPL (Standard PHP Library) which offers several Iterators that can do all the work for you. PHP配备了SPL(标准PHP库) ,它提供了多个迭代器 ,可以为您完成所有工作。

A few to check out would be RecursiveIteratorIterator and RecursiveArrayIterator 要检查的几个是RecursiveIteratorIteratorRecursiveArrayIterator

I combined both ways and created DSL: 我结合了两种方式并创建了DSL:

A ($subnodes) {
    $ret = '';
    foreach ($subnodes as $subnode) {
        $ret .= WALK($subnode);
    }

    return $ret;
}
B ($n) { /*...*/ }
C ($n) { /*...*/ }
D ($subnode) { /*...*/ }
E () { /*...*/ }
F () { /*...*/ }
G () { /*...*/ }
H ($n) { /*...*/ }

that is translated to PHP. 即翻译为PHP。

I recommend this library: https://packagist.org/packages/lukascivil/treewalker 我推荐这个图书馆: https : //packagist.org/packages/lukascivil/treewalker

TreeWalker is a simple and small Library that will help you to work faster with manipulation of structures in PHP TreeWalker是一个简单的小型库,它将帮助您更快地处理PHP中的结构

  • getdiff() - Get json difference getdiff()-获取json差异
  • walker() - Edit json (Recursively) walker()-编辑json(递归)
  • structMerge() - Joins two structures structMerge()-连接两个结构
  • createDynamicallyObjects() - Create nested structure by Dynamic keys createDynamicallyObjects()-通过动态键创建嵌套结构
  • getDynamicallyValue() - Dynamically get a structure property getDynamicallyValue()-动态获取结构属性
  • setDynamicallyValue() - Dynamically access a structure property to set a value setDynamicallyValue()-动态访问结构属性以设置值

I made a simple recursive function that effectively walks a tree. 我做了一个简单的递归函数,可以有效地走树。 Here it is 这里是

   function deep_cetegories($categories){
     foreach($categories as $category)
  {
    print_r((json_encode($category['category_name'])));
    if(isset($category['children']))
    {
        deep_cetegories($category['children']);
    }

  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PHP中“foreach x除了y”最优雅的方法是什么? - What is the most elegant way to do “foreach x except y” in PHP? 在PHP中定义全局常量数组的最“优雅”方法是什么 - What is the most “elegant” way to define a global constant array in PHP 哪种方法使大型HTML代码适应可变数量的PHP变量是最有效/最优雅的方法? - Which is the most efficient / most elegant way to adapt large HTML code to variable number of PHP variables? 用Doctrine向后遍历OneToOne表实体的优雅方法 - Elegant way to walk backward through OneToOne table entities with Doctrine 从包含元素的键的值枚举多维PHP数组上的键的最优雅方法是什么? - What's the most elegant way to enumerate keys on a multidimensional PHP array from the value of a contained element's key? 在PHP中逐字段添加多维数组的最优雅方法是什么? - What's the most elegant way to add up multidimensional arrays field by field in PHP? PHP-检查字符串是否仅包含整个或半个十进制数字的最优雅的方法? - PHP - most elegant way to check if a string contains only a whole or half decimal number? 要求 parent::__construct() 的最优雅方式 - The most elegant way to require parent::__construct() 什么是重新排列关联数组的最优雅方式? - Whats the most elegant way to rearrange an associative array? Facebook canvas应用最优雅的方式 - Facebook canvas application most elegant way
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM