Click here to Skip to main content
15,880,543 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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.
Posted
Updated 23-Jan-14 9:56am
v3
Comments
Matt T Heffron 23-Jan-14 16:03pm    
You say "my object is not a treeview nor is it a c# object it returns a result from a query to a server"
By the time the code sees it, it is a c# object.
It may not have been before the query that returns it, but it is at any point that matters to the recursion.

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#[^]
 
Share this answer
 
v2
Comments
stixoffire 23-Jan-14 11:24am    
Yes I read these two articles and I am still a bit at a loss. Most of the recursion examples I have read go back to showing code for a structure like Directories and files - which is good except if you can imagine all my objects are the same with exception they can be flagged as Item or NotItem[branch] and all of these can have children or not and the children can be either branch or item , many to many not just one to many and to build a datatable of these objects showing relationship seems to allude me. If it was just one to many that part is simple. my pseudo code is GetBranches if HasChildren GetBranches, GetItems - I do not have a way to simply get all (Branches and items) , I have to request either a branch or an item and then test for children and recurse - if I could get all - much easier.. I am trying to build a Parent Child relationship model form the objects
bowlturner 23-Jan-14 12:41pm    
Are you sure many to many? I mean can there be circular references? A is child of B who is child of C who has A as child?
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:
C#
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:
C#
flatListTreeNodes = buildFlatListTreeNodes(treeView1.Nodes);
 
Share this answer
 
v2
Comments
stixoffire 23-Jan-14 12:33pm    
I updated the question to provide some clarity , because I have two methods for getting the object collections [which I cannot change] (GetBranch, GetItem) there is no GetAll , Branches can have items and items can have branches. So I am not sure how to recurse that structure , it seems like your method of using a stack might be the direction I need to go, but it almost seems as if I will need to keep track somehow.
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:
C#
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);
    }
  }
}

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>.

Edit:
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:
Edit2: changed for different signature of GetItems and GetBranches.
C#
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);
}

Pre-order vs. post-order:
Given:
Root -+- R1 --- R11
      |
      +- R2 -+- R21
             |
             +- R22

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

Edit 3:
C#
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:
c3
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".
 
Share this answer
 
v5
Comments
stixoffire 23-Jan-14 14:17pm    
This seems closer and simpler to answer your question about flattening, no I would like to gather in the objects as they are in the object itself. I am presenting the visualization of those objects (imagine a blackbox that you would like to know what is in there) ; so the blackbox contains the objects in a hierarchical structure and I want to visually represent them. My hangup has been recursion as you mentioned because each of the items or branches could have items or branches and I had these two fixed methods that I had to use to do the recursion. Yes you are also correct I do not wish to loop forever. I will try your code and see if that does the trick for me - I have not used LINQ but I see it can be pretty powerful from your example. almost forgot - yes I would be returning the table built from the recursion.
Matt T Heffron 23-Jan-14 14:30pm    
So, you could use the DoSomething(n) to draw the visualization of a node, or could construct a List of some object with the Node and any additional information useful for the visualization, etc.
stixoffire 23-Jan-14 16:56pm    
Thank you for your replies; I might be overlooking something here or overthinking , but if object n does not contain the getItems(server, root) method can I use just the method call, nn.name is the root that I am passing to each of these methods but nn does not exist in the context .
Matt T Heffron 23-Jan-14 17:01pm    
I changed the solution for different signature of GetItems and GetBranches.
Matt T Heffron 23-Jan-14 17:46pm    
I edited again to give a hierarchical representation.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900