基于ID和ParentID的Php排序

时间:2012-05-23 09:52:27

标签: php arrays multidimensional-array

我有以下数组结构:

   |  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)
  • 之后直接列出
  • 没有孩子的RootCategories,列在数组的末尾。 (示例TVShows)

我如何用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 个答案:

答案 0 :(得分:1)

将主阵列拆分为两个,一个是那些没有子节点的节点,另一个是具有剩余项目的节点。

使用array_multisort函数对项目数组进行排序,并使用所需条件对没有子项的类别数组进行排序。最后一步是将没有孩子的数组推送到另一个。

这种形式不是最有效的,但是第一种方法是有效的,在此之后,你可以节省时间来优化代码。

答案 1 :(得分:1)

$input = array(
    array("foo", "bar", "5"),
    array("barr", "baz", "9"),
    array("nyan", "nyu", "2")
);

usort($input, function($a, $b) {
    if($a[2] < $b[2]) {
        return -1;
    } else if($a[2] > $b[2]) {
        return 1;
    } else {
        return 0;
    }
});

var_dump($input);
你是说这样的意思吗?我们的想法是使用您知道的条件手动比较数组的内容。由于要排序的东西是唯一的,因此必须始终实现逻辑如何排序。使用PHP,PHP的排序功能大部分时间都能正确完成。

答案 2 :(得分:1)

我很确定这不会回答你的问题,但可能会给你一些如何让你的生活更轻松的想法。这是问题的javascript方法,但这样你甚至不必考虑排序任何东西。您只需提供父母和孩子,它就会为您排序并随时可以使用。在我看来,这是一个非常好的方式。然而,它可能与您尝试做的事情无关,但也许对于其他类似问题,您会将此视为一种解决方案:https://developers.google.com/chart/interactive/docs/gallery/orgchart

答案 3 :(得分: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 [▶]
    ]
  ]
]