#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)
}
}
Для тех, у кого такая же проблема с вложенными комментариями, это хорошее решение для их сортировки.