6

すぐに主な問題を掘り下げましょう。次のような入力があります

$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'),
);

入力配列をループして、このような出力結果を作成するのに最適で高速な関数はどれですか?

4

5 に答える 5

18

ネストされたセットの操作は、再帰の完璧なケースです。

あなたのデータを考えると:

$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
        )

)
于 2013-06-08T13:12:16.970 に答える
0

There is a bug with above function. The top category of second array of the @tree is removed. This is the fix:

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]);
    }
}
于 2014-03-20T08:21:32.080 に答える
0

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;
}
于 2014-04-05T09:56:22.407 に答える