如何形成我的节点和树通用类 [英] How To Form my Node and Tree Generic Classes

查看:147
本文介绍了如何形成我的节点和树通用类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 IList< Category>



SQL Server:



Table:Category



CategoryID,ParentCategoryID
$ p

所以如果我有这个包含节点关系的IList类,那么我试图找出它是如何适用的像很多人在做一个Node和Tree一样。那么构造函数看起来和这个类是如何创建的?



对于泛型,我并不是很难核心。我认为在这里创建一个通用的Node类和Tree类是很有意义的,所以我可以在将来重用它,以供其他树类型使用。

所以如果我有类似的东西这是什么,T是如何使用,我从中受益?



(伪码在这里)

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

private void SetParentNode(T)
private void AddChild(T)
$ b $ ...等

试图理解这里的概念,为什么Generic Node类将用于像Childeren等包含子/父关系(int Ids)

更新



因此,GroupBy建议存在问题。看看我试图用你的例子做什么:



首先我在我的Tree类中有这个属性:



public Dictionary,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.ParentId上分组,但我想要(尽管在ToDictionary中的节点),并且List>是来自Parent Node.Children属性的子节点列表。

解决方案

  public class TreeNode< T>这是一个更完整的实现。 
{
private T _item;
私人TreeNode< T> _parentNode;
私人列表< 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; }
}
$ b $ 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);


$ / code $ / pre

你的问题:

构造函数将如何创建并根据使用情况创建此类?

正如您从在上面的 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(rootGroup中的var类别)
{
//创建并填充类别
var node = new TreeNode< Category>(category);
ConstructChildrenCategories(节点,组);
categories.Add(node);


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

foreach(组中的var类)
{
//创建并填充类别
var childNode = new TreeNode< Category>(category);
ConstructChildrenCategories(childNode,groups);

//我们可以在两种方法中自动执行此操作。
childNode.SetParent(node.Item);
node.AddChild(childNode);
}
}


I've got an IList<Category>

The Category type is coming from my Category Table in SQL Server:

Table: Category

CategoryID, ParentCategoryID

so typical heirarchy in one table.

So if I have this IList of Categories that contain the node relationships, then I am trying to figure out how this fits into making a Node and Tree like a lot of people are doing. And how would the constructor look and this class be created in terms of usage?

I am not hard core on Generics so bare with me. I think it makes sense here to create a generic Node class and Tree class so I can reuse in the future I think for other tree types.

So if I have something like this, how is T being used and what am I benefiting from?

(pseudo code here)

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

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

... etc.

trying to understand the concept here on why a Generic Node class would be used for any type coming in like Childeren, etc. that contains a child/parent relationship (int Ids)

UPDATE

So having an issue here with the GroupBy recommendation. Check out what I tried to do with your example:

First I have this property in my Tree class:

public Dictionary, IList>> ParentNodeAndRelatedChildrenFlattenedMap { get; private set; }

and incoming to my class's constructor is a IList dependencies that I converted (looped and created a new Node for every one of them) to a IList>

Now I'm trying to group that list by Node.ParentId as you were talking so that I get a grouping on Parent Nodes and since each node has its children property it's easy to find out what the related children are to those parent nodes.

But here is the problem now later down in my code:

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

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

    ParentNodeAndRelatedChildrenFlattenedMap = dictionary;
}

well it's not liking my assignment of dictionary because it's an > dictionary that's created by the ToDictionary(). So not sure how to get this grouping grouped and to a dictionary that is a , List> where Node in the dictionary is the Node instance for that parent I'm grouping on (yea I'm grouping on its Node.ParentId but I want the Node though in the ToDictionary in the end) and the List> is the list of Children Nodes from the Parent Node.Children property.

解决方案

This is what a more complete implementation would look like:

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);
    }
}

And your questions:

How would the constructor look and this class be created in terms of usage?

As you can see from the above in AddChild(), simply specify the type of the child for the constructor.

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

So if I have something like this, how is T being used and what am I benefiting from?

The use of generics can same a lot of time rewriting code when done right. In the implementation above, we can make a tree structure out of basically any type we want by simply changing T. So this saves us a lot of time if we need a tree structure for more than one type.

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

Generically really take some exposure time before it clicks and you "just get it", keep at it.

Constructing the tree

To construct the tree from a list of categories that may or may not have parent categories you will need to iterate through the list in some way. A decent way to go about this would be to first organise them into groupings based on the ParentCategoryID and constructing the tree. Something like this (untested):

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);
    }
}

这篇关于如何形成我的节点和树通用类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆