1

次のように格納されている配列があります。

[0] => Array
    (
        [id] => 1
        [cat_name] => c1
    )

[1] => Array
    (
        [id] => 2
        [cat_name] => c2
        [copii] => Array
            (
                [0] => Array
                    (
                        [id] => 5
                        [cat_name] => c21
                    )

                [1] => Array
                    (
                        [id] => 6
                        [cat_name] => c22
                    )

            )

    )

[2] => Array
    (
        [id] => 3
        [cat_name] => c3
        [copii] => Array
            (
                [0] => Array
                    (
                        [id] => 7
                        [cat_name] => c31
                        [copii] => Array
                            (
                                [0] => Array
                                    (
                                        [id] => 9
                                        [cat_name] => c311
                                    )

                            )

                    )

                [1] => Array
                    (
                        [id] => 8
                        [cat_name] => c32
                    )

            )

    )

特定の ID へのルートを見つける簡単な方法を見つけようとしています。現在、foreach を使用して、考えられるすべての配列を反復処理し、ルートを見つけています。

例:

id = 1:
     route[0][id]=1,route[0][cat_name]=c1
id = 5:
    route[0][id]=2,route[0][cat_name]=c2
    route[1][id]=5,route[1][cat_name]=c21
id = 9:
    route[0][id]=3,route[0][cat_name]=c3
    route[1][id]=7,route[1][cat_name]=c31
    route[2][id]=9,route[2][cat_name]=c311

私の質問が意味をなさない場合は、それに対する適切な解決策を見つけるのに何時間も費やしたせいだと思います...

4

4 に答える 4

1

たくさんのコードを投稿する代わりに、再帰について知らない場合は、再帰について読むことをお勧めします。PHP は再帰があまり得意ではありませんが、本当に唯一の選択肢です。

基本的に、配列、検索する ID、およびパスを表す文字列/配列を取る関数を呼び出します。最初に、後者のパラメーターに空の文字列または空の配列を指定して呼び出します。

関数では、次のようにします。

  • のトップレベルで foreach を実行します$array
  • 探している が見つかったら$id、 を返します$path
  • 配列値の 1 つがサブ配列である場合は、現在の ID ノードを追加し、それを使用して関数を再度呼び出します$foundPath = findPath( $array, $id, $path )
  • 何かを返す場合$foundPathは、パスがあり、戻ることができます。
  • 何も見つからなかった場合 ($foundPath以下のように false または null である場合)、そのままにして、ループの次の反復に進みます。
  • ループの最後で何も見つからなかった場合は、false または null を返します。

それが役立つことを願っています!

于 2009-12-02T09:23:53.627 に答える
1

再帰はあなたが望むものです:

<?php

    function walk_array(array $a, &$ra, $path, $depth = 0) {
     $id= isset($path[$depth]) ? $path[$depth] : null;
     if (!is_null($id)) {
      foreach ($a as $a2) {
       if ($a2['id'] == $id) {
        $ra[$depth]= $a2;
        unset($ra[$depth]['copii']);
        // This is the key bit - recursion is simply a function calling itself:
        if (isset($a2['copii']))
         walk_array($a2['copii'], $ra, $path, ++$depth);
       }
      }
     }
    }

    $complex_array= array(
      array('id'=> 1, 'name'=> 'Node #1', 'copii'=> array(
       array('id'=> 3, 'name'=> 'Node #3', 'copii'=> array(
         array('id'=> 4, 'name'=> 'Node #4')
       ))
      )),
      array('id'=> 2, 'name'=> 'Node #2', 'copii'=> array(
       array('id'=> 5, 'name'=> 'Node #5', 'copii'=> array(
         array('id'=> 6, 'name'=> 'Node #6',)
       ))
      )),
    );    

    // Prints out nodes 1,3,4 in order
    $ra= array();
    walk_array($complex_array, $ra, array(1, 3, 4));
    print_r($ra);

    // Prints out nodes 2,5,6 in order
    $ra= array();
    walk_array($complex_array, $ra, array(2, 5, 6));
    print_r($ra);

    // Prints out empty array
    $ra= array();
    walk_array($complex_array, $ra, array(5, 2, 4));
    print_r($ra);

    // Prints out nodes 2,5 in order
    $ra= array();
    walk_array($complex_array, $ra, array(2, 5));
    print_r($ra);
?>
于 2009-12-02T09:30:25.813 に答える
0

私が考えることができるもう1つの方法-再帰を回避する-は、「変数変数」を使用することです。そのため、配列インデックスの可能なすべての組み合わせを、ある程度まで試してみてください。

$search = 3;
$ind = '$arr[0][copii][1]'; // generated somehow
if ( isset(${$ind}['id']) && ${$ind}['id'] == $search ) {
  // we found it
}

これには同じくらい時間がかかり、何かが見つかる保証はありません。また、これを書いているとき、$ind値を生成する確実な方法を考えるのに苦労しています...再帰は別として。000、001、002 などの 3 桁の数字を生成し、各文字を使用して 、 、 などのインデックスを作成できると$arr[0][copii][0][copii][0]思い$arr[0][copii][0][copii][1]ます$arr[0][copii][0][copii][2]

この方法はまだ完全ではありません。間違いなく値を見逃し、存在しない多くの値を探すからです。正直なところ、再帰はコード的にはよりシンプルでクリーンなオプションであり、配列に何百ものエントリがない限り、大きなパフォーマンスの問題に気付くことはありません。

于 2009-12-03T17:17:18.987 に答える
0

あなたの質問は本当に意味がありません。「ルートを見つける」とはどういう意味ですか?

配列にはグラフを記述する再帰構造があるようです。最短経路を見つけるためのグラフ トラバーサル アルゴリズムの方が適切かもしれません (つまり、配列をグラフ データ構造に変換します。おそらくノード リスト + エッジ リストであり、その上でグラフ アルゴリズムを実行します)。

于 2009-12-02T09:14:34.767 に答える