0

私は次の配列構造を持っています:

   |  ID  |  CategoryName  | ParentID 
    _________________________________
       1  |  Movies        | -1
    _________________________________
       2  |  Series        | -1
    _________________________________
       3  |  ActionMovies  |  1
    _________________________________
       4  |  HorrorMovies  |  1
    _________________________________
       5  |  ComedySeries  |  2
    _________________________________
       6  |  TVShows       | -1

私の目標は、次の構造に到達することです

ゴール:

   |  ID  |  CategoryName  | ParentID 
    _________________________________
       1  |  Movies        | -1
    _________________________________
       3  |  ActionMovies  |  1
    _________________________________
       4  |  HorrorMovies  |  1
    _________________________________
       2  |  Series        | -1
    _________________________________
       5  |  ComedySeries  |  2
    _________________________________
       6  |  TVShows       | -1

または言葉で説明:

  • 親カテゴリにあるParentID = -1(映画の例)
  • すべてのカテゴリは元の ID 番号を保持します
  • ParentCategory の直後にリストする必要があります (ActionMovies の例)
  • Children のない RootCategories は、配列の最後にリストされます。(テレビ番組の例)

PHPでこれを最善に達成するにはどうすればよいですか? 元のMysqlクエリにアクセスできないため、それはオプションではありません:)

私はこのコードから始めましたが、それが正しい道であり、最小限の労力/読みやすさであるかどうかはわかりません

        $tmpList = Categories_Models_Main::getAllCategories();



    $categoryData = array();
    foreach ($tmpList as $index => $categoryObject) {
        $categoryData[] = array('id' => $categoryObject->id,
                                 'CategoryName' => $categoryObject->parentId,
                                 'name' => $categoryObject->name);


    }

    ///let us assume $categoryData is original state.

    ///Beginning of manipulation and re-sorting of $tmpList


    foreach ($categoryData as $key => $value) {

        $mainId[$key] = $value['id'];

        $parentId[$key] = $value['parentId'];

    }

    array_multisort($parentId, $mainId, $categoryData);
4

4 に答える 4

1

メイン配列を2つに分割します。1つは子を持たないノードを持ち、もう1つは残りのアイテムを持ちます。

array_multisort関数を使用してアイテムの配列に並べ替えを行い、必要な基準を使用して子のないカテゴリの配列に並べ替えも行います。最後のステップは、子のない配列を他の配列にプッシュすることです。

この形式は最も効率的ではありませんが、最初のアプローチを使用することは有効です。その後、コードを最適化する時間を節約できます。

于 2012-05-23T10:09:03.100 に答える
1

これがあなたの質問に答えていないことは確かですが、あなたの人生を楽にする方法についていくつかのアイデアを与えるかもしれません. これは問題に対する JavaScript のアプローチですが、この方法ではソートについて考える必要さえありません。親と子を提供するだけで、ソートされてすぐに使用できます。私の意見ではかなり良い方法です。それでも、おそらくあなたがやろうとしていることとは無関係ですが、他の同様の問題については、これを解決策として見ることができます: https://developers.google.com/chart/interactive/docs/gallery/orgchart

于 2012-05-23T10:37:32.543 に答える
0

この問題を解決する唯一の方法は、ボトムアップ アプローチを使用することです (私はピラミッドについて言及しています)。

説明

親を持たない配列内の行 (エントリ) から始める必要があります。私の場合、「parent_id = 0」を持つ要素です。それらを取得したら、各親要素の子要素を構築する必要があります。

後者の部分は、処理中の要素に子がなくなるまで、並べ替えメソッドを呼び出すことによって再帰的に行われます。並べ替えメソッドの結果は、配列が完了するまで前の配列ポイントに渡されます。

コード

Class Categories {
    private $cats;

    public function getAllCategoriesSorted() {
        /**
         * $this->cats = [
         *      'id' => x, 'parent_id' => x
         * ];
         */
        $this->cats = Category::get()->toArray();

        # find categories with no parents
        $keys = array_keys(array_column($this->cats, 'parent_id'), 0);

        $return = [];
        # loop through each and populate each one
        foreach ($keys as $key) {
            $return[$this->cats[$key]['id']] = $this->sortCategories($this->cats[$key]);
        }

        dd($return);
    }

    private function sortCategories($currentElement) {
        # we need to check if current element has any children
        $keys = array_keys(array_column($this->cats, 'parent_id'), $currentElement['id']);

        if ($keys === false || empty($keys)) {
            # we are dealing with childless element, we should return it as it is
            return $currentElement;
        }

        # we are dealing with element that has children, we need to loop through each child
        $currentElement['children'] = [];

        foreach ($keys as $key) {
            $currentElement['children'][$this->cats[$key]['id']] = $this->sortCategories($this->cats[$key]);
        }

        return $currentElement;
    }
}

結果の例

array:2 [▼
  65 => array:4 [▼
    "id" => 65
    "name" => "Parent 1"
    "parent_id" => 0
    "children" => array:14 [▼
      66 => array:4 [▼
        "id" => 66
        "name" => "Child 1"
        "parent_id" => 65
        "children" => array:22 [▶]
      ]
      87 => array:4 [▼
        "id" => 87
        "name" => "Child 2"
        "parent_id" => 65
        "children" => array:31 [▶]
      ]
      117 => array:4 [▶]
      118 => array:4 [▶]
      120 => array:4 [▶]
      124 => array:4 [▶]
      125 => array:4 [▶]
      127 => array:4 [▶]
      225 => array:4 [▶]
      305 => array:4 [▶]
      434 => array:4 [▶]
      321 => array:4 [▶]
      348 => array:4 [▶]
      468 => array:4 [▶]
    ]
  ]
  64 => array:4 [▼
    "id" => 64
    "name" => "Parent 2"
    "parent_id" => 0
    "children" => array:5 [▼
      128 => array:4 [▶]
      132 => array:4 [▼
        "id" => 132
        "name" => "Child 3"
        "parent_id" => 64
        "children" => array:22 [▼
          202 => array:3 [▶]
          203 => array:3 [▼
            "id" => 203
            "name" => "Child 4"
            "parent_id" => 132
          ]
          204 => array:3 [▶]
          205 => array:3 [▶]
          206 => array:3 [▶]
          207 => array:3 [▶]
          208 => array:3 [▶]
          209 => array:3 [▶]
          210 => array:3 [▶]
          211 => array:3 [▶]
          212 => array:3 [▶]
          213 => array:3 [▶]
          214 => array:3 [▶]
          215 => array:3 [▶]
          216 => array:3 [▶]
          217 => array:3 [▶]
          218 => array:3 [▶]
          220 => array:3 [▶]
          221 => array:3 [▶]
          222 => array:3 [▶]
          223 => array:3 [▶]
          224 => array:3 [▶]
        ]
      ]
      134 => array:4 [▶]
      394 => array:4 [▶]
      454 => array:4 [▶]
    ]
  ]
]
于 2017-09-05T10:35:52.090 に答える