Ответы пользователя по тегу Алгоритмы
  • Древовидные комментарии

    nixmale
    @nixmale
    Если речи идет о SQL, то есть одно очень хорошее решение для сортировки древовидных комментариев в один SQL запрос без LEFT JOIN, кстати которое с применением AJAX позволяет перезагружать отдельные ветки, начинающиеся с любого комментария в цепочки.

    Предположим добавление комментариев к теме выглядит следующим образом:
    $arr = array(
         array('id'=>1, 'pid'=>0, 'name'=>'Comment 1'),
          array('id'=>2, 'pid'=>1, 'name'=>'Comment 1.1'),
          array('id'=>3, 'pid'=>1, 'name'=>'Comment 1.2'),
          array('id'=>6, 'pid'=>1, 'name'=>'Comment 1.3'),
           array('id'=>4, 'pid'=>2, 'name'=>'Comment 1.1.1'),
           array('id'=>5, 'pid'=>2, 'name'=>'Comment 1.1.2'),
           array('id'=>7, 'pid'=>2, 'name'=>'Comment 1.1.3'),
         array('id'=>8, 'pid'=>0, 'name'=>'Comment 2'),
          array('id'=>12, 'pid'=>8, 'name'=>'Comment 2.1'),
          array('id'=>17, 'pid'=>8, 'name'=>'Comment 2.2'),
           array('id'=>13, 'pid'=>12, 'name'=>'Comment 2.1.1'),
            array('id'=>16, 'pid'=>13, 'name'=>'Comment 2.1.1.1'),
         array('id'=>9, 'pid'=>0, 'name'=>'Comment 3'),
          array('id'=>14, 'pid'=>9, 'name'=>'Comment 3.1'),
           array('id'=>15, 'pid'=>14, 'name'=>'Comment 3.1.1'),
         array('id'=>10, 'pid'=>0, 'name'=>'Comment 4'),
         array('id'=>11, 'pid'=>0, 'name'=>'Comment 5'),
         );
    


    Каждый комментарий имеет id и id родителя (pid). Ответ на тему должен принимать pid = 0, а ответ на комментарий — id комментария на который отвечаете соответственно. В конечном итоге дерево должно выглядеть так, как показано в массиве образце.

    Чтобы раскрыть дерево за 1 SQL, достаточно достать из базы все комментарии имеющие идентификатор темы, отсортировав их так: ORDER BY pid ASC, id ASC. В результате получим следующий массив.

    $arr = array(
         array('id'=>1, 'pid'=>0, 'name'=>'Comment 1'),
         array('id'=>8, 'pid'=>0, 'name'=>'Comment 2'),
         array('id'=>9, 'pid'=>0, 'name'=>'Comment 3'),
         array('id'=>10, 'pid'=>0, 'name'=>'Comment 4'),
         array('id'=>11, 'pid'=>0, 'name'=>'Comment 5'),
          array('id'=>2, 'pid'=>1, 'name'=>'Comment 1.1'),
          array('id'=>3, 'pid'=>1, 'name'=>'Comment 1.2'),
          array('id'=>6, 'pid'=>1, 'name'=>'Comment 1.3'),
           array('id'=>4, 'pid'=>2, 'name'=>'Comment 1.1.1'),
           array('id'=>5, 'pid'=>2, 'name'=>'Comment 1.1.2'),
           array('id'=>7, 'pid'=>2, 'name'=>'Comment 1.1.3'),
         array('id'=>12, 'pid'=>8, 'name'=>'Comment 2.1'),
          array('id'=>17, 'pid'=>8, 'name'=>'Comment 2.2'),
          array('id'=>14, 'pid'=>9, 'name'=>'Comment 3.1'),
          array('id'=>13, 'pid'=>12, 'name'=>'Comment 2.1.1'),
           array('id'=>16, 'pid'=>13, 'name'=>'Comment 2.1.1.1'),
           array('id'=>15, 'pid'=>14, 'name'=>'Comment 3.1.1'),
         );
    


    Теперь требуется изменить структуру массива.

         for ($i = 0, $c = count($arr); $i < $c; $i++)
         {
           $new_arr[$arr[$i]['pid']][] = $arr[$i];
         }
    


    И завершающая рекурсионная функция.

         function my_sort($data, $parent = 0, $level = 0)
         {
           $arr = $data[$parent];
    
           for($i = 0; $i < count($arr); $i++)
           {
             echo '<div style="padding-left:' . $level . 'px;">';
             echo $arr[$i]['name'];
               if(isset($data[$arr[$i]['id']])) my_sort($data, $arr[$i]['id'], 20);
             echo '</div>';
           }
         }
    


    Теперь чтобы показать все дерево одним разом, достаточно вызвать

    my_sort($new_arr, 0);
    Ответ написан
    6 комментариев