Сортировка комментариев и ответов на основе родительского значения в списке массивов (вложенные комментарии)

#java #android #kotlin

#java #Android #kotlin

Вопрос:

У меня есть список с комментариями и ответами. если комментарий является ответом, он совпадает с родительским значением. Я хочу, чтобы комментарии были поверх ответов.(Я хочу вложенные комментарии) Это мой список:

     sortedComment.add(CommentTest(id=1, parent=0))
    sortedComment.add(CommentTest(id=2, parent=0))
    sortedComment.add(CommentTest(id=3, parent=0))
    sortedComment.add(CommentTest(id=4, parent=1))
    sortedComment.add(CommentTest(id=5, parent=2))
    sortedComment.add(CommentTest(id=6, parent=3))
    sortedComment.add(CommentTest(id=7, parent=6))
    sortedComment.add(CommentTest(id=8, parent=6))
    sortedComment.add(CommentTest(id=9, parent=2))
    sortedComment.add(CommentTest(id=10, parent=5))
    sortedComment.add(CommentTest(id=11, parent=5))
    sortedComment.add(CommentTest(id=12, parent=13))
    sortedComment.add(CommentTest(id=13, parent=4))
 

Я хочу отсортировать их следующим образом:

     1 -> comment
    4 --> replay for 1
    13 --> replay for 4
    12 --> replay for 13
    2 -> comment
    9 --> replay for 2
    5 --> replay for 2
    10 -->replay for 5
    11 --> replay for 5
    3 -> comment
    6 --> replay for 3
    7 --> replay for 6
    8 --> replay for 6
 

У меня уже есть какое-то решение, но оно не работает. Это мои решения:

решение 1:

     var index = -1
    var replyIndex: Int
    sortedComment.forEach { comment ->
        replyIndex = -1
        index  
        if (comment.parent != 0) {
            sortedComment.forEach { reply ->
                replyIndex  
                if (comment.parent == reply.id) {
                        Collections.swap(sortedComment, index, replyIndex 1 )
                }
            }
        }
    }
 

решение 2:

         for (comment in sortedComment){
        if (sortedComment2.size==sortedComment.size) break
        if (comment.parent==0)
            sortedComment2.add(comment)
            sortedComment.forEach { reply->
            if (comment.id==reply.parent){
                sortedComment2.add(reply)
                sortedComment.forEach {cg->
                    if (reply.id==cg.parent)
                        sortedComment2.add(cg)
                }
            }
        }
    }
 

Я был бы очень признателен, если бы кто-нибудь мог помочь.

Ответ №1:

То, что вы хотите, выглядит следующим образом:

 ArrayList <CommentTest> sortedList = new ArrayList<>();
for(int i = 0; i < sortedComment.size(); i  ) {
    CommentTest comment = sortedComment.get(i);
    if(comment.getParent() == 0) {
      sortedList.add(comment);
      LinkedList<Integer> to_search = new LinkedList<Integer>();
      to_search.addFirst(comment.getId());
      while(!to_search.isEmpty()){
          for(int j = i   1; j < sortedComment.size(); j  ) {
              CommentTest c = sortedComment.get(j);
              if(c.getParent() == to_search.getFirst()) {
                 sortedList.add(c);
                 to_search.addLast(c.getId());
               }
          }
          to_search.removeFirst();
      }
    }
}
 

Логика, которой я следовал, заключалась в следующем: сначала мы начинаем с добавления комментария (я предполагаю, что они будут первыми). Допустим, id = 1, затем мы ищем родителя, который соответствует этому id , т.Е. id =?, parent = 1 .

Когда мы находим повтор, родительский элемент которого соответствует идентификатору текущего повтора / комментария (т. Е. c.getParent() == to_search.getFirst() ), Мы добавляем его в отсортированный список (т.Е. sortedList.add(c); ). Затем мы повторяем тот же процесс, но на этот раз для того родительского элемента, который мы только что нашли. Следовательно, почему я добавил этого родителя id в список элементов для поиска (т.Е. to_search.addLast(c.getId()); ). После завершения поиска я удаляю этот элемент из верхней части стека to_search.removeFirst(); .

Весь поиск повтора повтора… комментарий останавливается, когда в стеке больше нет элементов для поиска while(!to_search.isEmpty()) .

Вся эта логика заключается в том, что я хотел убедиться, что после определенного комментария все его ответы идут первыми, например:

  2 -> comment
 9 --> replay for 2
 5 --> replay for 2
 

и не какой-то повтор кулака повтора. Однако, если это не является жестким ограничением для критериев сортировки, которые вы используете, и сортировка, подобная этой: 1 4 13 12 2 5 10 11 9 3 6 7 8 является допустимой. Затем мы можем упростить код для чего-то гораздо более простого, например:

 void sort_comments(List <CommentTest> unsorted, List <CommentTest> sorted, int parentID){
    for (CommentTest c :  unsorted){
         if (c.getParent() == parentID){
             sorted.add(c);
             sort_comments(unsorted, sorted, c.getId());
         }
    }
}
 

Или еще более элегантно с использованием потоков :

 void sort_comments(List <CommentTest> unsorted, List<CommentTest> sorted, int parentID){
  unsorted.stream().filter(c -> c.getParent() == parentID).forEach(c -> { sorted.add(c); 
        sort_comments(unsorted, sorted, c.getId()); });
}
 

Ответ №2:

 // creates map {parent -> list of children}
// {0=[1, 2, 3], 1=[4], 2=[5, 9], 3=[6], 6=[7, 8], 5=[10, 11], 13=[12], 4=[13]}
val map = sortedComment.groupBy({ it.parent }, { it.id })

// recursively adds the ids of children
// for example if key == 2 it will add 5 from [5, 9] then 10 from [10, 11], 
// then 11, then it will go back to [5, 9] and will take 9 (result [5, 10, 11, 9])
fun helper(key: Int): List<Int> = map[key]?.flatMap { listOf(it)   helper(it) } ?: listOf()

val result = helper(0) // [1, 4, 13, 12, 2, 5, 10, 11, 9, 3, 6, 7, 8]
 

Ответ №3:

Спасибо, ребята. Я думаю, что у меня есть решение для теста с лучшей производительностью:

 private fun sortComment(parentId: String,sortedList:ArrayList<Item>){
    for (comment in unsortedList){
        if (sortedList.size==unsortedList.size) break
        if (comment.parent!=parentId)
            continue
        sortedList.add(comment)
        sortComment(comment.id!!,sortedList)
    }
}
 

Для тех, у кого такая же проблема с вложенными комментариями, это хорошее решение для их сортировки.