Комментарии, как в VK

Давайте представим, что нам нужно отобразить комментарии так, что они цепляются к самому верхнему родителю и дальше не вкладываются друг в друга. Но при этом, на каждом комментарии указано, к какому комментарию этот комментарий является ответом.

Назовём это 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}");
        }
    }
}

Если вы нашли ошибку, пожалуйста выделите её и нажмите Ctrl+Enter.


Leave a Reply

Your email address will not be published. Required fields are marked *