1

基本的にツリーを形成するネストされたコメントのリストがあります。

//Non-Relevant properties (Like Body, Creator etc) excluded
internal class Comment
{
    public int ID { get; set; }
    public int ItemID { get; set; }
    public int ParentItemID { get; set; }
    public List<Comment> ChildComments { get; set; }
}

Postsまず、データベースからリストを取得し、次にすべてを取得しますComments where ItemID == Posts[all].id

フラットリストをループして、ネストされたリストまたはツリーリストを作成したいと思います。

こんなふうになります:

の場合、ParentItemID == 0トップレベルのコメントがあります。コメントParentItemID > 0と照合する必要がある場合は、子コメントを親コメントリストに追加します。ParentItemIDID

私が立ち往生しているのは、過去に再帰を使用してファイルやフォルダーをナビゲートしたことだけです。これでは、コレクションをインスタンス化して、その後の再帰を通じてそれを保持することはできません。

また、再帰の外でリストをインスタンス化し、アイテムを追加するたびにすべてのアイテムをループするのはばかげているようです。

これを行うための良い堅実なパターンがあると確信しています、私はそれを見つけることができません。

4

3 に答える 3

4

すべてのコメントをループして、それぞれの子コメントを取得できます。

foreach (Comment comment in comments) {
  comment.ChildComments =
    comments.Where(c => c.ParentItemID == comment.ItemID).ToList();
}

パフォーマンスが向上する別の方法(必要な場合)は、上のコメントをグループ化し、そこからをParentItemID作成してDictionary<int, List<Comment>>から、上記のようにコメントをループして、辞書からリストを取得することです。

于 2012-08-28T22:56:16.630 に答える
3

Guffaのソリューションはずっときれいですが、ここに別の方法があります。

    public static List<Comment> ToTree(List<Comment> FlatCommentsList)
    {
        List<Comment> TopComments = FlatCommentsList.Where<Comment>(x => x.ParentItemID == 0).ToList();

        List<Comment> NestedComments = FlatCommentsList.Where<Comment>(x => x.ParentItemID > 0).ToList();

        List<int> IdsToRemove;

        while (NestedComments.Count > 0)
        {
            IdsToRemove = new List<int>();

            NestedComments.ForEach(x =>
            {
                Comment ParentComment = TopComments.Where<Comment>(y => y.ItemID == x.ParentItemID).SingleOrDefault<Comment>();

                if (ParentComment != null)
                {
                    ParentComment.ChildComments.Add(x);
                    IdsToRemove.Add(x.ItemID);
                }    
            });

            NestedComments.RemoveAll(x => IdsToRemove.Contains(x.ItemID));
        }

        return TopComments;
    }

再帰もありませんが、その役割は果たします。私は再帰が大好きですが、ここでは必要ないと思います。

于 2012-08-28T23:03:37.030 に答える
1

GroupByトップレベルのコメントとネストされたコメントの分離は、LINQと:を使用して実行できます。

var grouped = comments.GroupBy(c => c.ParentItemId == 0);
var topLevel = grouped.Single(g => g.Key);
var nested = grouped.Single(g => !g.Key);

(これらの操作の結果は、シーケンスを反復処理するか、シーケンスなどのメソッドを使用するまで、実際には計算されませんToList()

ネストされたコメントを親に添付することは、Guffaのアプローチのように行うことができます(コメントが多い場合は遅く、余分なメモリを使用しません)、または従来の時間と空間のトレードオフを行うことができます(コメントが多い場合は速く、追加のメモリが必要です)。

var dictionary = comments.ToDictionary(c => c.Id);
foreach (nested as comment) {
    dictionary[comment.ParentItemId].ChildComments.Add(comment);
}
于 2012-08-28T23:04:40.323 に答える