1

を持っていますIList<Category>

カテゴリ タイプは、SQL Server のカテゴリ テーブルから取得されます。

表: カテゴリ

カテゴリ ID、親カテゴリ ID

1つのテーブルに典型的な階層があります。

したがって、ノードの関係を含むカテゴリの IList がある場合、多くの人が行っているように、これがノードとツリーの作成にどのように適合するかを理解しようとしています。そして、コンストラクターはどのように見え、このクラスは使用に関してどのように作成されるでしょうか?

ここでは、一般的な Node クラスと Tree クラスを作成して、将来他のツリー タイプで再利用できるようにするのが理にかなっていると思います。

では、このようなものがある場合、T はどのように使用され、何から恩恵を受けているのでしょうか?

(疑似コードはこちら)

public class Node<T>
...
    Node<T> _parentNode;
    List<Node<T>> _children;

    private void SetParentNode(T)
    private void AddChild(T)

... etc.

ここで、子/親の関係 (int Id) を含む Childeren などの任意の型に Generic Node クラスが使用される理由についての概念を理解しようとしています。

アップデート

したがって、ここで GroupBy の推奨事項に問題があります。あなたの例で私が何をしようとしたかをチェックしてください:

まず、Tree クラスに次のプロパティがあります。

パブリック ディクショナリ、IList>> ParentNodeAndRelatedChildrenFlattenedMap { get; プライベートセット; }

そして、クラスのコンストラクターに着信するのは、IList> に変換した (ループして、それらのすべてに対して新しいノードを作成した) IList 依存関係です。

今、あなたが話していたように、そのリストを Node.ParentId でグループ化しようとしています。これにより、親ノードでグループ化されます。各ノードには子プロパティがあるため、それらの親ノードに関連する子が何であるかを簡単に見つけることができます。

しかし、これが私のコードの後半にある問題です。

public void CreateFlattenedMap()
{
    var parentGroups = _nodeDependencies.GroupBy(d => d.ParentNodeId);

    var dictionary = parentGroups.ToDictionary(d => d, d => d.ToList());

    ParentNodeAndRelatedChildrenFlattenedMap = dictionary;
}

それは、ToDictionary() によって作成された > 辞書であるため、私の辞書の割り当てが好きではありません。したがって、このグループ化をグループ化して , List> であるディクショナリに取得する方法がわからない場合、ディクショナリ内の Node は、グループ化している親の Node インスタンスです (はい、その Node.ParentId でグループ化していますが、 Node は最後に ToDictionary に含まれます)、List> は Parent Node.Children プロパティからの子ノードのリストです。

4

3 に答える 3

3

より完全な実装は次のようになります。

public class TreeNode<T>
{
    private T _item;
    private TreeNode<T> _parentNode;
    private List<TreeNode<T>> _children;

    public TreeNode(T item)
    {
        _item = item;
    }

    public void SetParentNode(T parent)
    {
        _parentNode.Item = parent;
    }

    public T Item
    {
        get { return _item; }
        set { _item = value; }
    }

    public void AddChild(T child)
    {
        _children.Add(new TreeNode<T>(child));
    }

    public void RemoveChild(T child)
    {
        var node = _children.FirstOrDefault(e => e.Item.Equals(child));
        if (node != null)
            _children.Remove(node);
    }
}

そしてあなたの質問:

コンストラクターはどのように見え、このクラスは使用に関してどのように作成されますか?

上記の からわかるようにAddChild()、コンストラクターの子の型を指定するだけです。

var node = new TreeNode<T>(item);

もし私がこのようなものを持っているとしたら、それはどのようTに使われ、何の恩恵を受けているのでしょうか?

ジェネリックの使用は、正しく行われた場合、コードを書き換えるのに多くの時間を費やす可能性があります。上記の実装では、単純に を変更するだけで、基本的に任意の型からツリー構造を作成できますT。したがって、複数のタイプのツリー構造が必要な場合、これにより多くの時間を節約できます。

var intTreeNode = new TreeNode<int>(10);
var stringTreeNode = new TreeNode<string>("hello world");

一般的に、クリックする前に実際に露出時間がかかり、「すぐに理解できる」ので、そのままにしてください。

ツリーの構築

親カテゴリがある場合とない場合があるカテゴリのリストからツリーを構築するには、何らかの方法でリストを反復処理する必要があります。ParentCategoryIDこれを行うための適切な方法は、最初にツリーを構築することに基づいてそれらをグループに編成することです。このようなもの(テストされていません):

public List<TreeNode<Category>> ConstructCategories(List<Category> categories)
{
    var groups = categories.GroupBy(e => e.ParentCategoryID);
    var rootGroup = groups.Single(e => e.Key == null);
    var categories = List<TreeNode<Category>>();

    foreach (var category in rootGroup)
    {
        // Create and fill category
        var node = new TreeNode<Category>(category);
        ConstructChildrenCategories(node, groups);
        categories.Add(node);
    }
}

public void ConstructChildrenCategories(TreeNode<Category> node, IEnumerable<IGrouping<Category>> groups)
{
    var group = groups.Single(e => e.Key == node.Item.CategoryID);

    foreach (var category in group)
    {
        // Create and fill category
        var childNode = new TreeNode<Category>(category);
        ConstructChildrenCategories(childNode, groups);

        // We could do this automatically in both methods.
        childNode.SetParent(node.Item);
        node.AddChild(childNode);
    }
}
于 2013-03-29T05:53:05.887 に答える
2

これは役立つかもしれません:

public interface ICategory
{
    int Id { get; }
    int ParentId { get; }
}

public class Category : ICategory
{
    int id;
    int parentId;

    public int Id { get { return id; }}
    public int ParentId { get { return parentId; }}
}

そして、これはNodeクラスです:

public class Node<T> where T : ICategory
{
    Node<T> _parentNode;
    List<Node<T>> _children;

    public Node<T> Parent { get { return _parentNode; }}

    public Node<T> Child(int index) { return _children[index]; }

    public T Value;

    public Node(T value)
    {
        this.Value = value;
    }

    public void AddChild(T item)
    {
        Node<T> child = new Node<T>(item);
        this._children.Add(child);
        child._parentNode = this;
    }
}

そして、これはTreeクラスです:

public class Tree<T> where T : ICategory
{
    List<Node<T>> values;

    public Tree()
    {
        this.values = new List<Node<T>>();
    }

    public Node<T> FindNode(int id)
    {
        if (values.Exists(input => input.Value.Id == id))
        {
            return values.Find(input => input.Value.Id == id);
        }
        else { return null; }

    }

    public void AddNode(T value)
    {
        Node<T> parent = FindNode(value.ParentId);

        if (parent != null)
        {
            parent.AddChild(value);
        }
    }
}
于 2013-03-29T06:08:39.750 に答える
-1

tree と treenode のすべての機能を作成することはできません。

代わりに、クラス データを Treenode に追加します。

例えば

class MyClass
{
    public int A;
    public string B;
}

...

TreeNode Node = TreeView.Nodes.Add("AAA");
MyClass Data = new MyClass();
Node.Tag = Data;

TreeNode に割り当てられた Data は削除されません。また、ツリー全体のプロパティと Nodes メンバーも使用できます。

ノードのデータを使用するときに行うべき唯一のことは、型キャストです。

TreeNode Node = TreeView.Nodes[0];
MyClass Temp = Node.Tag as MyClass;
于 2016-09-08T14:17:30.157 に答える