24

ツリー構造で表現できるように、それ自体のリストを持つ1つのクラスがあります。

これらのクラスのフラット リストをプルしており、フラット化を解除したいと考えています。

public class Group
{
     public int ID {get;set;}

     public int? ParentID {get;set;}

     public List<Group> Children {get;set;}

}

次のことができるようになりたい

List<Group> flatList = GetFlatList() //I CAN ALREADY DO THIS
List<Group> tree = BuildTree(flatList);

親グループの ID プロパティに関連する ParentID (明らかでない場合)。

編集

単一のオブジェクトではなくリストを返す理由については、いくつかの混乱があります。

項目のリストを持つ UI 要素を作成しています。それぞれに子があります。したがって、最初のリストにはルート ノードがありません。これまでのところ、すべてのソリューションが機能していないようです。

これが意味することは、基本的に Group クラスを使用したツリー型構造のリストが必要だということです。

4

3 に答える 3

44

BuildTreeメソッドが返される理由がわかりません。List<Group>ツリーにはルートノードが必要なためGroup、リストではなく単一の要素を返すことを期待する必要があります。

で拡張メソッドを作成しますIEnumerable<Group>

public static class GroupEnumerable
{
    public static IList<Group> BuildTree(this IEnumerable<Group> source)
    {
        var groups = source.GroupBy(i => i.ParentID);

        var roots = groups.FirstOrDefault(g => g.Key.HasValue == false).ToList();

        if (roots.Count > 0)
        {
            var dict = groups.Where(g => g.Key.HasValue).ToDictionary(g => g.Key.Value, g => g.ToList());
            for (int i = 0; i < roots.Count; i++)
                AddChildren(roots[i], dict);
        }

        return roots;
    }

    private static void AddChildren(Group node, IDictionary<int, List<Group>> source)
    {
        if (source.ContainsKey(node.ID))
        {
            node.Children = source[node.ID];
            for (int i = 0; i < node.Children.Count; i++)
                AddChildren(node.Children[i], source);
        }
        else
        {
            node.Children = new List<Group>();
        }
    }
}

使用法

var flatList = new List<Group>() {
    new Group() { ID = 1, ParentID = null },    // root node
    new Group() { ID = 2, ParentID = 1 },
    new Group() { ID = 3, ParentID = 1 },
    new Group() { ID = 4, ParentID = 3 },
    new Group() { ID = 5, ParentID = 4 },
    new Group() { ID = 6, ParentID = 4 }
};


var tree = flatList.BuildTree();
于 2013-04-07T20:53:53.257 に答える