【问题标题】:How do I format Nested Set Model data into an array?如何将嵌套集模型数据格式化为数组?
【发布时间】:2013-06-04 16:06:51
【问题描述】:

让我们马上挖掘主要问题,我有这样的输入

$category = array(
  'A' => array('left' => 1, 'right' => 8),
  'B' => array('left' => 2, 'right' => 3),
  'C' => array('left' => 4, 'right' => 7),
  'D' => array('left' => 5, 'right' => 6),
  'E' => array('left' => 9, 'right' => 10),
);

我希望输出是这样的

$tree = array(
  array('A', 'B'),
  array('A', 'C', 'D'),
  array('E'),
);

哪一个是循环输入数组并创建这样的输出结果的最佳且快速的函数?

【问题讨论】:

  • 你应该包括从第一个结构到第二个结构的转换的业务逻辑。目前还不是很清楚。
  • 您想要的输出不反映嵌套集。应该更像array(A => array(B => null, C => array(D => null), E => null)
  • @hw 这里的业务逻辑是en.wikipedia.org/wiki/Nested_set_model
  • @Steven Moseley:该输出使函数难以思考。
  • @quocnguyen.clgt - 我不明白你的评论。您是说 1) 很难以我上面显示的格式创建输出,还是 2) 使用该格式的输出很困难?我不明白为什么以嵌套集以外的方式输出嵌套集数据是有意义的。上面您想要的输出看起来比正确结构化的数据更难使用

标签: php nested-set-model


【解决方案1】:

使用嵌套集是递归的完美案例。

鉴于您的数据:

$category = array(
    'A' => array('left' => 1, 'right' => 9),
    'B' => array('left' => 2, 'right' => 4),
    'C' => array('left' => 5, 'right' => 8),
    'D' => array('left' => 6, 'right' => 7),
    'E' => array('left' => 10, 'right' => 11),
);

以下内容会将您的嵌套集合数据分解为 PHP 中正确嵌套的数组:

function createTree($category, $left = 0, $right = null) {
    $tree = array();
    foreach ($category as $cat => $range) {
        if ($range['left'] == $left + 1 && (is_null($right) || $range['right'] < $right)) {
            $tree[$cat] = createTree($category, $range['left'], $range['right']);
            $left = $range['right'];
        }
    }
    return $tree;
}

$tree = createTree($category);
print_r($tree);

输出:

Array
(
    [A] => Array
        (
            [B] => Array
                (
                )

            [C] => Array
                (
                    [D] => Array
                        (
                        )

                )

        )

    [E] => Array
        (
        )

)

然后,您可以使用以下内容将正确的树展平为您想要的格式:

function flattenTree($tree, $parent_tree = array()) {
    $out = array();
    foreach ($tree as $key => $children) {
        $new_tree = $parent_tree;
        $new_tree[] = $key;
        if (count($children)) {
             $child_trees = flattenTree($children, $new_tree);
            foreach ($child_trees as $tree) {
                $out[] = $tree;
            }
        } else {
            $out[] = $new_tree;
        }
    }
    return $out;
}

$tree = flattenTree($tree);
print_r($tree);

输出:

Array
(
    [0] => Array
        (
            [0] => A
            [1] => B
        )

    [1] => Array
        (
            [0] => A
            [1] => C
            [2] => D
        )

    [2] => Array
        (
            [0] => E
        )

)

【讨论】:

    【解决方案2】:

    如果你不想使用递归:

    foreach ($category as $name => $range) {
        $line[$range['left']] = $name;
        $line[$range['right']] = $name;
    }
    
    ksort($line);
    $count = 0;
    
    foreach($line as $name) {
        if ( ! isset($open[$name])) {
            $open[$name] = true;
            $result[$name] = true;
            $count++;
        } else {
            unset($open[$name]);
            if ($count > 0) {
                $count = 0;
                $tree[] = array_keys($result);
                $result = $open;
            } else {
                $result = array();
            }
        }
    }
    

    【讨论】:

    • 递归对于处理潜在的无限嵌套级别是必要的。你测试过这个吗?
    【解决方案3】:

    另一种解决方案,无需递归(请测试)

    $result = array();
    
        foreach($category as $key => $value) {
    
            /*Get current row index*/
            $i = count($result);
    
            if($i == 0) {
                $result[] = array($key);
            } else {
    
                $iParent = -1;
    
                /*Find parent index*/
                for($j = count($result[$i-1]) - 1; $j >= 0; $j--) {
                    if($value['left'] > $category[$result[$i-1][$j]]['left'] 
                        && $value['right'] < $category[$result[$i-1][$j]]['right']) {
                        $iParent = $j;
                        break;
                    }
                }
    
                if($iParent == -1) { $result[] = array($key);}
    
                if($iParent == count($result[$i-1]) - 1) {
                    // append to last
                    $result[$i-1][] = $key;
                } else {
                    // make new list
                    $result[$i] = array_slice($result[$i-1], 0, $iParent + 1);
                    $result[$i][] = $key;
                }
            }
        }
    
        print_r($result);
    

    【讨论】:

      【解决方案4】:

      上述功能存在错误。 @tree 的第二个数组的顶级类别被删除。这是修复:

      foreach ($category as $name => $range) {
          $line[$range['left']] = $name;
          $line[$range['right']] = $name;
      }
      
      ksort($line);
      $tree = array();
      $count = 0;
      
      foreach ($line as $name) {
          if (!isset($open[$name])) {
              $open[$name] = true;
              $count++;
          }
          else {
              if ($count > 0) {
                  $count = 0;
                  $tree[] = array_keys($open);
              }
              unset($open[$name]);
          }
      }
      

      【讨论】:

        【解决方案5】:

        我很少修改 Stiven 的代码。

        public function createTree($category, $left = 0, $right = null) {
            $tree = array();
            foreach ($category as $cat => $range) {
                if ($range['clf'] == $left + 1 && (is_null($right) || $range['crt'] < $right)) {
                    $tree[$cat]= array();
                    $tree[$cat]['title']=$range['title'];
                    if($range['crt']-$range['clf']>1){
                        $tree[$cat]['sub'] = $this->createTree($category, $range['clf'], $range['crt']);
                    }
                    $left = $range['crt'];
                }
            }
            return $tree;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-23
          • 1970-01-01
          • 1970-01-01
          • 2019-02-26
          • 2019-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多