0

ツリーに変換する必要がある 2 次元の PHP 配列があります。各内部配列の「パス」値は、現在のノードへの列挙パスです。(このアイデアは、Bill Karwin の SQL Antipatterns に関する本から得ました)。

したがって、私が始めている配列は次のようになります。

array(
[1] => array('name' => 'Animals', 'path' => '1/'),
[2] => array('name' => 'Birds', 'path' => '1/3/'),
[3] => array('name' => 'Cockatoos', 'path' => '1/3/5/'),
[4] => array('name' => 'Fish', 'path' => '1/2/'),
[5] => array('name' => 'Kookaburras', 'path' => '1/3/4/')
)

お気づきかもしれませんが、外側の配列のインデックスは無意味です。「名前」で内側の配列をアルファベット順に並べただけで、PHP は外側の配列に数値インデックスを割り当てました。

「パス」値に関する限り、各パスの最後のセグメントはノードの疑似 ID です。つまり、動物はノード 1、鳥はノード 3 です。完全なパスが指定された場所へのルートを記述していることがわかります。ノード、たとえば、'Cockatoos' は 'Birds' の親になり、'Birds' は 'Animals' の親になります。

ノードのアルファベット順を維持したいのですが、親でグループ化します。つまり、次のような配列が必要です (自然な順序で):

[1]         => 'Animals'
[1][3]      => 'Birds'
[1][3][5]   => 'Cockatoos'
[1][3][4]   => 'Kookaburras'
[1][2]      => 'Fish'

これを再帰的に繰り返して、ツリーの視覚的表現を出力する予定です。

あるタイプの配列から別のタイプの配列に変換しようとする際に、私のアプローチでは再帰、変数変数、および正規表現を使用しましたが、障害が発生し続けています。

また、考えるべき SPL データ構造または反復子はありますか?

どうもありがとう!

編集:申し訳ありませんが、ツリーの深さは可変であることに言及する必要がありました。上記の例では 3 つのレベルがありますが、実際にはさらに多くのレベルがあります。

キム

4

1 に答える 1

2

これは、ツリーの深さに関係なく、Eval() 関数 (評価の略) を使用することで可能になります。しかし、アルファベットのソートはまだ適切に機能していません。親配列のインデックスは同じままであるため、混同されます。しかし、少なくともあなたはすでにツリーを構築することができます:)

<?php
$a = array(
        array('name' => 'Animals', 'path' => '1/'), 
        array('name' => 'Birds', 'path' => '1/3/'), 
        array('name' => 'Eagles', 'path' => '1/3/3/'),
        array('name' => 'Cockatoos', 'path' => '1/3/5/'), 
        array('name' => 'Fish', 'path' => '1/2/'), 
        array('name' => 'Kookaburras', 'path' => '1/3/4/')
    );
Iterate($a);
$tree = Iterate($a);

var_dump($tree);

OneLevelDeeper($tree);
var_dump($tree);

function Iterate($ChildArray)
{
    $TreeArray;
    foreach($ChildArray as $Key => $Value)
    {
        //echo $Key.': '.$Value['name']."\r\n";
        $exp = explode('/', $Value['path']);
        $path;
        foreach($exp as $int)
        {
            if($int != "")
            {
                $path[] = $int;
            }
        }

        //Using Eval() function of PHP
        $BuildSourceToEvaluate = '$TreeArray';
        for($i=0; $i<(count($path)-1); $i++)
        {
            $BuildSourceToEvaluate .= '[$path['.$i.']]';
        }
        $BuildSourceToEvaluate .= '[] = $Value[\'name\'];';
        echo $BuildSourceToEvaluate."\r\n";
        Eval($BuildSourceToEvaluate);
        //print_r($path);
        /*
        switch(count($path))
        {
            case 0:
            break;
            case 1:
                $TreeArray[] = $Value['name']; 
                //$TreeArray[$path[0]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                //$TreeArray[$path[0]][] = $Value['name']; //Use this for non-unique tree paths
            break;
            case 2:
                $TreeArray[$path[0]][] = $Value['name']; 
                //$TreeArray[$path[0]][$path[1]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                //$TreeArray[$path[0]][$path[1]][] = $Value['name']; //Use this for non-unique tree paths
            break;
            case 3:
                $TreeArray[$path[0]][$path[1]][] = $Value['name'];
                //$TreeArray[$path[0]][$path[1]][$path[2]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                //$TreeArray[$path[0]][$path[1]][$path[2]][] = $Value['name']; //Use this for non-unique tree paths
            break;
        }
        */
        unset($path);
    }
    return $TreeArray;
}


function OneLevelDeeper(&$a)
{
    sort($a);
    foreach($a as $Key => $Value)
    {
        if(is_array($Value))
        {
            sort($a[$Key]);
            OneLevelDeeper($a[$Key]);
        }
    }
}

?>
于 2012-10-14T07:23:02.540 に答える