【问题标题】:Convert tree to list of full paths in PHP将树转换为 PHP 中的完整路径列表
【发布时间】:2018-10-04 12:29:45
【问题描述】:

我正在尝试将树结构转换为路径列表。

树看起来像这样:

array (
  0 => 
  array (
    'name' => 'Default Category',
    'children' => 
    array (
      0 => 
      array (
        'name' => 'Carpet',
        'children' => 
        array (
          0 => 
          array (
            'name' => 'Colour',
            'children' => 
            array (
              0 => 
              array (
                'name' => 'White',
                'children' => 
                array (
                ),
              ),
              1 => 
              array (
                'name' => 'Grey',
                'children' => 
                array (
                ),
              ),
              2 => 
              array (
                'name' => 'Black',
                'children' => 
                array (
                ),
              ),
              3 => 
              array (
                'name' => 'Light',
                'children' => 
                array (
                ),
              ),
              4 => 
              array (
                'name' => 'Medium',
                'children' => 
                array (
                ),
              ),
              5 => 
              array (
                'name' => 'Dark',
                'children' => 
                array (
                ),
              ),
            ),
          ),
          1 => 
          array (
            'name' => 'Style',
            'children' => 
            array (
              0 => 
              array (
                'name' => 'Twist Pile Carpets',
                'children' => 
                array (
                ),
              ),
              1 => 
              array (
                'name' => 'Stainfree Carpets',
                'children' => 
                array (
                ),
              ),
              2 => 
              array (
                'name' => 'Saxony and Shagpile Carpets',
                'children' => 
                array (
                ),
              ),
              3 => 
              array (
                'name' => 'Soft Carpets',
                'children' => 
                array (
                ),
              ),
              4 => 
              array (
                'name' => 'Loop Pile & Berber Carpets',
                'children' => 
                array (
                ),
              ),
              5 => 
              array (
                'name' => 'Wool Carpets',
                'children' => 
                array (
                ),
              ),
              6 => 
              array (
                'name' => 'Striped & Patterned Carpet',
                'children' => 
                array (
                ),
              ),
              7 => 
              array (
                'name' => 'Natural Carpets',
                'children' => 
                array (
                ),
              ),
            ),
          ),

我的最终结果将是一个如下所示的数组:

Default Category/
Default Category/Carpet
Default Category/Carpet/Colour
Default Category/Carpet/Colour/White
Default Category/Carpet/Colour/Grey
Default Category/Carpet/Colour/Black
...
Default Category/Carpet/Style/
Default Category/Carpet/Style/Twist Pile Carpets
Default Category/Carpet/Style/Stainfree Carpets

我知道我需要在这里使用递归并且可以迭代树,但我不确定如何在遍历树时构建路径列表。

我尝试过搜索,但没有找到任何与我特别需要的东西相近的东西,而且我似乎有这样的印象,即我正在使用的树是一棵多路树,处理起来略有不同。

一些建议是简化树,但我已经通过删除其他不必要的键来做到这一点,并且我已经看到了扁平化数组以使遍历过程更容易的建议,但我不清楚这将如何工作.

任何帮助将不胜感激。

更新 2

这是我目前拥有的,它适用于第一个路径,即:默认类别/地毯/颜色/白色,但第二个路径不会携带默认类别/地毯/颜色/,这最终就是我想知道该怎么做。

function generateCategoryPaths($categoryTree, &$paths = null, &$path = null)
{
    if (! $paths) {
        $paths = [];
    }

    foreach ($categoryTree as $category) {
        $path .= $category['name'];
        if (isset($category['children']) && count($category['children']) > 0) {
            $path .= '/';
            generateCategoryPaths($category['children'], $paths, $path, $level);
            continue;
        }

        $paths[] = $path;
        $path = '';
    }

    return $paths;
}

以及调用代码:

$categoryPaths = generateCategoryPaths($categories);

这将返回以下内容:

array (
  0 => 'Default Category/Carpet/Colour/White',
  1 => 'Grey',
  2 => 'Black',
  3 => 'Light',
  4 => 'Medium',
  5 => 'Dark',
  6 => 'Style/Twist Pile Carpets',
  7 => 'Stainfree Carpets',
  8 => 'Saxony and Shagpile Carpets',
  9 => 'Soft Carpets',
  10 => 'Loop Pile & Berber Carpets',
  11 => 'Wool Carpets',
  12 => 'Striped & Patterned Carpet',
  13 => 'Natural Carpets',
  14 => 'Brand',
  15 => 'Room/Bedroom Carpet',
  16 => 'Living Room Carpet',
  17 => 'Hall, Stairs & Landing Carpet',
  18 => 'Office Carpet',
  19 => 'Conservatory Carpet',
  20 => 'Dining Room Carpet',
  21 => 'Whole House',
  22 => 'Vinyl/Colour/White',
  23 => 'Grey',
  24 => 'Black',
  25 => 'Light',
  26 => 'Medium',
  27 => 'Dark',
  28 => 'Style/Wood Effect Luxury Vinyl Flooring',
  29 => 'Tile Effect Luxury Vinyl Flooring',
  30 => 'Parquet Luxury Vinyl Flooring',
  31 => 'Plain',
  32 => 'Brand/Naturelle',
  33 => 'TLC',
  34 => 'Karndean Flooring',
  35 => 'Polyflor Flooring',
  36 => 'Amtico',
  37 => 'Quickstep Livyn',
  38 => 'COREtec Flooring',
  39 => 'Installation/Click Vinyl Flooring',
  40 => 'Stick Down Vinyl Flooring',
  41 => 'Laminate/Colour/White',

第一行是我试图为每个条目复制它,它显示了通过树的路径。

第二行和后续行将丢弃当前路径,这就是我要解决的问题。

更新 3

输入树的 JSON 编码版本:

[{"name":"Default Category","level":"1","children":[{"name":"Carpet","level":"2","children":[{"name":"Colour","level":"3","children":[{"name":"White","level":"4","children":[]},{"name":"Grey","level":"4","children":[]},{"name":"Black","level":"4","children":[]},{"name":"Light","level":"4","children":[]},{"name":"Medium","level":"4","children":[]},{"name":"Dark","level":"4","children":[]}]},{"name":"Style","level":"3","children":[{"name":"Twist Pile Carpets","level":"4","children":[]},{"name":"Stainfree Carpets","level":"4","children":[]},{"name":"Saxony and Shagpile Carpets","level":"4","children":[]},{"name":"Soft Carpets","level":"4","children":[]},{"name":"Loop Pile & Berber Carpets","level":"4","children":[]},{"name":"Wool Carpets","level":"4","children":[]},{"name":"Striped & Patterned Carpet","level":"4","children":[]},{"name":"Natural Carpets","level":"4","children":[]}]}]}]}]

【问题讨论】:

  • 到目前为止你做了什么吗?
  • 你之前尝试过什么?
  • 我已经尝试了几件事,但我又回到了第一方。我将尝试返回到我必须提供一些上下文的版本。
  • 让我们看看你的“最佳”失败。帮我们一个忙——将您的输入数据发布为var_export() 或 json,以便我们可以快速着手解决您的问题。您是否研究过此站点上的许多递归解决方案?
  • 我已经添加了我最好的失败,尽管以前我什至没有像第一行显示我想要实现的那样接近。我还重新格式化了数组 - 感谢您的提示!在研究方面,我查看了其中的一些,但似乎没有一个对我拥有的树类型起作用。我确实尝试篡改它们以获得预期的效果,但我觉得我缺乏阵列处理部门,可悲的是,这从来都不是我的强项,我认为这就是我很难解决这个问题的原因。跨度>

标签: php recursion tree


【解决方案1】:

我建议使用带有引用变量的递归。一个引用变量,用这个符号“&”定义,使一个php变量异步工作,这意味着定义是统一的,不管它在哪里定义。

<?php
function listPaths(array $array=[], string $parent="", array &$names=[]):array
{

   foreach($array as $data){

     if(isset($data['name'])){
          $name = $parent."/".$data['name'];
          $names[] = $name;

        if(isset($data['children'])){
           listPaths($data['children'],$name,$names);
        }
     }
  }

    return $names;
}

$result = listPaths($array); 

【讨论】:

  • 这适用于列出每个类别的名称,但在我的情况下,我需要生成每个类别的路径,这就是我卡住的地方。
  • 应该可以的。
  • 效果很好。我已经尝试破解这个几个小时了,当我查看你的代码时,它看起来很简单!我想我的问题只是不知道如何以你的方式利用递归。可能对您没有任何影响,但我已将源代码中的解决方案归功于您。这肯定会帮助我在编程生涯中更上一层楼,对此我感激不尽。
【解决方案2】:

我创建了一个树生成器,它创建了一个带有&lt;li&gt;'s&lt;ul&gt;'s,它可以包含其他&lt;ul&gt;'s&lt;li&gt;'s。你可以在这里阅读我的博文https://delboy1978uk.wordpress.com/2014/12/06/tree-generator-for-multi-dimensional-arrays/

这不是您正在寻找的,但是调整这个类以生成斜杠而不是打开/关闭标签应该不会太难!回归策略才是最重要的!祝你好运!

class Tree
{
    private $data;
    private $html;

    public function buildTree(array $data, $parent_id)
    {
        $this->data = $data;
        $this->html = '<ul>';
        $this->getChildren($parent_id);
        $this->html .= '</ul>';
        return $this->html;
    }

    private function getChildren($parentId)
    {
        $children = array();
        foreach ($this->data as $row) {
            if ($row['parentid'] == $parentId) {
                $children[] = $row;
            }
        }
        foreach($children as $child)
        { 
            $this->html .= '<li>'.$child['name'].'<ul>';
            $this->getChildren($child['id']); 
            $this->html .= '</ul></li>';
        } 

    }
}


$tree = new Tree();
$ul = $tree->buildTree($data, 0);
echo $ul;

【讨论】:

  • 如果我的树有父子 ID,我认为这适用于我的用例,但也许,这就是为什么我一开始就觉得这很困难。我觉得递归是一个非常简单的概念,但我在现实世界中使用的并不多。
猜你喜欢
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 2017-03-16
  • 2013-06-29
  • 2014-10-29
  • 2012-04-01
  • 2013-12-20
相关资源
最近更新 更多