2

私はこのような配列を持っています

array(
    1 => array(
        'id'     => 1,
        'name'   => 'first',
        'parent' => null
    ),
    2 => array(
        'id'     => 2,
        'name'   => 'second',
        'parent' => null
    ),
    3 => array(
        'id'     => 3,
        'name'   => 'third',
        'parent' => 1
    ),
    4 => array(
        'id'     => 4,
        'name'   => 'fourth',
        'parent' => 3
    ),
    5 => array(
        'id'     => 5,
        'name'   => 'fifth',
        'parent' => 1
    ),        
);

しかし、「子」アイテムを配列の下の「子」キーに移動したいと思います。だから、私はで終わりたいです

array(
    1 => array(
        'id'       => 1,
        'name'     => 'first',
        'parent'   => null,
        'children' => array(
            3 => array(
                'id'       => 3,
                'name'     => 'third',
                'parent'   => 1,
                'children' => array(
                    4 => array(
                        'id'       => 4,
                        'name'     => 'fourth',
                        'parent'   => 3,
                        'children' => array()
                    ),
                )
            ),
            5 => array(
                'id'       => 5,
                'name'     => 'fifth',
                'parent'   => 1,
                'children' => array()
            )
        )
    ),
    2 => array(
        'id'       => 2,
        'name'     => 'second',
        'parent'   => null,
        'children' => array()
    )
);

しかし、正直なところ、どこから始めればよいかまったくわかりません。

配列内の各項目をループしてから、新しい配列を構築することを考えていました$new_array[$current['parent']]['children'][$current['id']] = $current;

しかし、ネストされたアイテムにヒットするとすぐに問題が発生します。

現在の配列と配列全体を受け取り、再帰的にツリーを上に移動してすべての親、したがってパス全体を見つける関数を作成できますが、親の 1 つがまだ作成されていない場合、再び問題が発生します。

私が考えることができる唯一のオプションは、さまざまなレベルの親の配列マップを作成し、それを再帰的にループして、すべての要素をそのように取得することですが、それはやや非効率的ですか?

誰でも解決策を提案できますか?

4

2 に答える 2

3

foreach ループについては正しい考えがありました。ただし、やりたいことには参照の「魔法」が必要です。

foreach($oldArray as $key => &$item) {
    if($item["parent"] == null) $newArray[$key] = &$item;
    else $oldArray[$item["parent"]]["children"][$key] = &$item;
}

unset($item);

これは「$oldArray」に対して出力されます

Array
(
[1] => Array
    (
        [id] => 1
        [name] => first
        [parent] => 
        [children] => Array
            (
                [3] => Array
                    (
                        [id] => 3
                        [name] => third
                        [parent] => 1
                        [children] => Array
                            (
                                [4] => Array
                                    (
                                        [id] => 4
                                        [name] => fourth
                                        [parent] => 3
                                    )

                            )

                    )

                [5] => Array
                    (
                        [id] => 5
                        [name] => fifth
                        [parent] => 1
                    )

            )

    )

[2] => Array
    (
        [id] => 2
        [name] => second
        [parent] => 
    )

[3] => Array
    (
        [id] => 3
        [name] => third
        [parent] => 1
        [children] => Array
            (
                [4] => Array
                    (
                        [id] => 4
                        [name] => fourth
                        [parent] => 3
                    )

            )

    )

[4] => Array
    (
        [id] => 4
        [name] => fourth
        [parent] => 3
    )

[5] => Array
    (
        [id] => 5
        [name] => fifth
        [parent] => 1
    )

)

そしてnewArray(「精製された」バージョン)の場合

Array
(
[1] => Array
    (
        [id] => 1
        [name] => first
        [parent] => 
        [children] => Array
            (
                [3] => Array
                    (
                        [id] => 3
                        [name] => third
                        [parent] => 1
                        [children] => Array
                            (
                                [4] => Array
                                    (
                                        [id] => 4
                                        [name] => fourth
                                        [parent] => 3
                                    )

                            )

                    )

                [5] => Array
                    (
                        [id] => 5
                        [name] => fifth
                        [parent] => 1
                    )

            )

    )

[2] => Array
    (
        [id] => 2
        [name] => second
        [parent] => 
    )

)

なぜこれが機能するのか: &item を foreach ループに入れることで、アイテムのコピーではなく参照を使用します。つまり、その項目について何を変更しても、対応する配列要素も変更されます。

&$item を $newArray[$key] または children 配列に渡すことで、参照を渡します...したがって、「元のオブジェクト」(つまり [3]) に対して行うことはすべて、すべてのオブジェクトに対しても行われます。参照。

$item の最後のインスタンスと変数の間のバインディングを消去するため、unset($item) が必要です。それ以外の場合は、$item 変数をもう一度変更するとすぐに、最後の変数も変更します。このスクリプトでは必ずしも必要ではありませんが、覚えておくとよい方法です。

于 2012-08-21T05:46:38.893 に答える
0

それらを配列からオブジェクトに変換できます。これは簡単に実行できます。すでにオブジェクト構造があります。

違いは、パラメータとして番号__construct()が渡される各オブジェクト内に関数を設定でき、関数内で子のマスター配列を調べて追加できることです。新しい子アイテムを追加すると、再び追加されます。この子の関数をトリガーします。これにより、配列内で自身の子が再度検索されます。ID__construct()__construct()

作業がほとんどない素晴らしいオブジェクトになってしまう可能性があります。それらを最後に配列として必要な場合は、heirachy全体を配列として返す関数を使用できますが、とにかくオブジェクトの方が優れていると思いませんか?

于 2012-08-21T05:47:53.997 に答える