Давайте представим, что нам нужно отобразить комментарии так, что они цепляются к самому верхнему родителю и дальше не вкладываются друг в друга. Но при этом, на каждом комментарии указано, к какому комментарию этот комментарий является ответом.
Назовём это thread’ом. Если у комментария нет родителя, то он считается корневым. Остальные комментарии отображаются под самым верхнем родителем. Т.е. если E – ответ на B, а B – ответ на C, то и B, и E отображаются на одной линии под C.
Модель будет такой:
class Comment
{
public readonly string Text;
public readonly Comment Parent;
public Comment(string text, Comment parent)
{
Text = text;
Parent = parent;
}
}
Метод для отображения с такой сигнатурой, в него приходят все комментарии для отображения:
public static void Draw(IEnumerable<Comment> comments) { }
Такой вызов:
Comments comments = new Comments();
var bookIsShit = comments.Reply("Книга говно!", null);
var youHaveAnError = comments.Reply("У вас ошибка во втором абзаце", null);
var iAgree = comments.Reply("Я согласен", bookIsShit);
var youDoNotUnderstandAnything = comments.Reply("Ты ничего не понимаешь!", iAgree);
var iDisagree = comments.Reply("Не согласен", bookIsShit);
var fixedIt = comments.Reply("Я исправил, спасибо!", youHaveAnError);
Draw(comments.AllComments);
Должен давать такой вывод:
Книга говно!
-Я согласен
-Ты ничего не понимаешь!
-Не согласен
У вас ошибка во втором абзаце
-Я исправил, спасибо!
И так, с чего начнём? Для начала добавим метод проверки есть ли определённый родитель у комментария на любом уровне вложенности (т.е. можно подниматься вверх сколько угодно):
class Comment
{
public readonly string Text;
public readonly Comment Parent;
public Comment(string text, Comment parent)
{
Text = text;
Parent = parent;
}
public bool HasParent(Comment targetParent)
{
var current = Parent;
while(current != null)
{
if (current == targetParent)
return true;
current = current.Parent;
}
return false;
}
}
С такой моделью решение будет проще простого 🙂
public static void Draw(IEnumerable<Comment> comments)
{
foreach (var root in comments.Where(comment => comment.Parent == null))
{
Console.WriteLine($"{root.Text}");
foreach (var children in comments.Where(comment => comment.HasParent(root)))
{
Console.WriteLine($"-{children.Text}");
}
}
}