如何递归多对父类子关系对象 [英] How do I recurse a many to many parent child kind of relationship object

查看:107
本文介绍了如何递归多对父类子关系对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象 - 如果你愿意的话就是一个黑盒子。在黑盒子里面存在物品和分支的分层集合,物品可以有分支,分支可以有物品。我试图将该结构直观地递归到表或绑定列表中(可能不可行);我有两个方法GetItems和GetBranches,我必须使用它来访问黑匣子内的结构。我将(Server,Root)的参数传递给这两个方法GetItems(server,root); GetBranches(服务器,根);其中server是我查询的系统,root是我希望在视觉上建模的分支和项目的元素。



已经发布了几个有用的代码示例,但我不是很清楚。请注意我的对象不是树视图,也不是ac#object它将查询结果返回给服务器,结果是一个对象集合,它们是项目或分支,具体取决于我调用的方法。

I have an Object - a black box if you will. Inside that blackbox exists a Hierarchical collection of items and branches , items can have branches and branches can have items. I am trying to recurse that structure visually into a table or bindinglist(probably not doable); I have two methods GetItems and GetBranches that I must use to access the structure inside the black box. I pass the arguments of (Server, Root) to these two methods GetItems(server, root) ; GetBranches(server,root); where server is the system I am querying, and root is the element whose branches and items I wish to model visually.

There have been a couple answers posted that are helpful code examples but I am not quite there. Please note my object is not a treeview nor is it a c# object it returns a result from a query to a server , the result is a collection of objects that are either items or branches depending on which method I called.

推荐答案

在这种情况下递归将是一个非常好的方法。



我不确定你是否在问如何递归或如何使用此特定对象。



这是一篇关于递归应该能够提供帮助的文章。



递归变得简单 [ ^ ]



这是另一个

使用C#的递归方法 [ ^ ]
Recursion would be a very good method to use on this situation.

I'm not sure if you are asking how to recurse or how with this specific object.

Here is an article on recursion that should be able to help.

Recursion made simple[^]

Here's another
Recursive methods using C#[^]


我在这里用一个例子回答了最近的一个问题使用堆栈执行的递归,与.NET中使用的更常见的递归技术相比提供了一些改进:[ ^ ]。



这是一个例子用于构建List< TreeNode>的典型递归例程的文件树视图控件中所有TreeNode的一部分:
I answered a recent question here with an example of recursion performed using a stack, which offers some improvements over the more common recursive technique used in .NET: [^].

Here's an example of a typical recursive routine to build a List<TreeNode> of all the TreeNodes in a TreeView Control:
private List<TreeNode> flatListTreeNodes = new List<TreeNode>();

private void buildFlatListTreeNodes(TreeNodeCollection theNodes)
{
    foreach (TreeNode theNode in theNodes)
    {
        flatListTreeNodes.Add(theNode);

        if (theNode.Nodes.Count > 0)
        {
            buildFlatListTreeNodes(theNode.Nodes);
        }
    }
}

你可以调用这样的方法:

You would call the method like this:

flatListTreeNodes = buildFlatListTreeNodes(treeView1.Nodes);


递归点是你似乎在苦苦挣扎的部分。

另外,如果这真的是多对多的,可能包括循环,你需要永远阻止循环。

对于第二个问题,使用 HashSet< T> 是一个很好的解决方案来跟踪节点已经访问过了。

您还没有表明是否需要退回展平集合,或者如果您需要在每个节点执行某些操作,那么我会做一些你可以改进的假设...

这样的事情:

The recursion point is the part where you seem to be struggling.
Also, if this is really many-to-many and may include cycles, you need to prevent looping forever.
For the second issue use of a HashSet<T> is a good solution to keep track of nodes already visited.
You haven't indicated if you need to return the collection flattened or if you need to perform some action at each node, so I'll make a few assumptions that you can refine...
So something like this:
HashSet<Node> Visited = new HashSet<Node>();
void Traverse(Node n)
{
  if (n == null)
    return;
  if (Visited.Add(n))
  {
    // perform the per-node action (if any) here
    DoSomething(n);
    // then deal with the "offspring"
    foreach (Node nn in n.GetItems().Concat(n.GetBranches()))  
    {
      Traverse(nn);
    }
  }
}



.Concat()是一个来自Linq的扩展方法( System.Linq )。

这相当于连续两个 foreach 循环 n.GetItems() n.GetBranches()

我假设这两个方法总是返回一些实现 IEnumerable< Node> 的东西。具体来说,当没有成员这样的项目时,他们返回一个空的集合对象而不是 null



如果您需要遍历所有 Node 的集合,那么 Visited 对象将包含(没有特别的顺序)并实现 IEnumerable< Node>



编辑:

如果对象确实是Hierarchical,即只有一条通往根节点的路径的树结构,则 HashSet 不是必需的,因为你永远无法访问一个节点不止一次,一个简单的节点列表就足够了:

Edit2:针对GetItems和GetBranches的不同签名进行了更改。 />


The .Concat() is an extension method from Linq (System.Linq).
It would be equivalent to just have two consecutive foreach loops on the n.GetItems() and n.GetBranches().
I'm assuming that those two methods always return something implementing IEnumerable<Node>. Specifically, they return a empty collection object not null when there are no such items as members.

If you need the collection of all of the Nodes traversed, then the Visited object will contain that (in no particular order) and implements IEnumerable<Node>.


If the objects really are Hierarchical, i.e. a tree structure with only one path to any node from the root, then the HashSet is not necessary because you can never get to a Node more than once, and a simple list of Nodes would suffice:
changed for different signature of GetItems and GetBranches.

List<Node> AllNodes = new List<Node>();
void Traverse(Node n)
{
  if (n == null)
    return;
  // For AllNodes in pre-order traversal add to AllNodes here:
  AllNodes.Add(n);
  // then deal with the "offspring"
  // assuming server is defined in an outer scope (i.e. a Field/Property of the class)
  // or it is trivially added as another parameter to the Traverse method
  foreach (Node nn in GetItems(server, n).Concat(GetBranches(server, n)))  
  {
    Traverse(nn);
  }
  // For post-order traversal add to AllNodes here:
  AllNodes.Add(n);
}



预订 vs。订购后:

鉴于:


Pre-order vs. post-order:
Given:

Root -+- R1 --- R11
      |
      +- R2 -+- R21
             |
             +- R22



预订是:

根R1 R11 R2 R21 R22

发布 - 订单是:

R11 R1 R21 R22 R2 Root



编辑3:


Pre-order is:
Root R1 R11 R2 R21 R22
Post-Order is:
R11 R1 R21 R22 R2 Root

Edit 3:

public class RepresentationNode
{
  public RepresentationNode()
  {
    Children = new List<RepresentationNode>();
  }
  public Node TheNode { get; set; }
  public List<RepresentationNode> Children { get; private set; }
}

RepresentationNode Traverse(AppropriateType server, Node n)
{
  RepresentationNode result = new RepresentationNode { TheNode = n };
  result.Children.AddRange(GetItems(server, n.name).Concat(GetBranches(server, n.name)).Select(nn => Traverse(server, nn)));
  return result;
}



我假设你有办法获得根节点以开始递归。

所以其他一些方法:


I assume you have some way to get the root Node in order to start the recursion.
so in some other method:

Node root = somehow get the root Node;
RepresentationNode hierarchy = Traverse(server, root);



此时你将拥有黑匣子的分层表示。


At this point you'll have a hierarchical representation of the "black box".


这篇关于如何递归多对父类子关系对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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