Tree filtering performance - c#

Currently I have a structure that looks like:
Name,Type, RefName, RefType
The goal is that the user selects an element and a direction and then get a treestructure in a webpage (JSON data) that displays all elements matching his criteria. As you can imagine, going up is not hard. The tree structure gets narrower and thus performance is no issue. While going down more and more nodes get added and at a certain point it gets slow. At this moment the nodes are added to a HashSet and I go recursively trough them. My program structure for going down is:
private void BuildChildNodes(ElementRefItem element, int goalDepth, int currentDepth =0)
{
if (goalDepth <= currentDepth)
{
return;
}
currentDepth++;
var elements = refElementRepository.All().Where(x => x.ElementName == element.Name);
foreach (var refElement in elements)
{
var node = CreateNode(refElement.ElementRefName, refElement.ElementRefType);
BuildChildNodes(node, goalDepth, currentDepth);
element.ChildNodes.Add(node);
}
}
I am looking for tips to optimize this part of the code. Are there other ways of doing this faster?
(Actual data structure is a bit more complex, but for clarity it is easier to show this version)

Instead of performing a query every time I retrieve the data once (all data is refreshed once a day) and I build two HashSets; one for parent-child relations and one for child-parent relations. This makes it possible to find an element in the HashTable (witch is very fast) and therefor retrieving the whole tree part. In meta code it looks like this:
- Create new cache (bottom up, top down)
- Foreach CachedObject
- Check if items exist (both parent and child)
: yes -> select node
: no -> create node and insert it in the new cache
- add child to parent node
This gives a hashset of Parent objects. Now you can select a parent object and automagically you get your whole tree section.

Related

Pre-order printing data from tree data

So, I have a tree data structure which should work fine but now I want to print the results. My problem is if the parent node has two children (right and left) which aren't null; what path should it take? If it takes lets say right then all of the left ones after that node get left out?
I want the tree to be in the correct order
Example of what it'll do if I do not order it correctly:
-----------------------------root---------------------------------------
-------------------value---------------skips this value-----------------
-------------value-------skips this value-- skips this value -- skips this value
----------value -------skips this value----- skips this value ---- skips this value
What I'd like it to do:
-----------------------------------root----------------------------------
---------------------------value-----------value-------------------------
----------------------value----value-----value---value-------------------
--------------------value--value--value-value-value-value-value
and so on(I'd continue on but it gets cluttered)
I'll need to place my nodes into a stack and order them in advance. Suggestions?

Get Collection after traversing in Umbraco

Here is my Project Folder Structure into Tree Structure
(*)Root
[]English
[1]Novel
[2]Thriller
[2.1]Happy
[2.1.1]Life Happy
HappyInLife
LoveInLife
[2.1.2]Joy
everywhereJoy
[2.1.3]Lauging
Always
Sometimes
Never
[2.2]Sad
[2.3]Excited
[2.4]Alone
[3]Love Story
[4]Action
[]Hindi
[]Marathi
Now here in the above structure I am at node [2.4]Alone
and I want to traverse at node [2.1]Happy. Further I want to access all children , sub children and sub .... of node [2.1] Happy.
My Project requirement is to display the node [2.1]Happy along with all its children and sub children and so on.... from the node [2.4]Alone
My Work up till now (I am at node [2.4]Alone)
var home=#Model.Parent.Children.First();
So home will have the node [2.1]Happy inside it.
but the problem is it will give me only the children of [2.1]Happy and not its Children's children and so on...
I tired using #Model.AncestorsOrSelf(3);
but not able to achieve my target .
Any help is appreciated
I suggest using uQuery: (1) (2)
Code would look like:
#using umbraco
var current = umbraco.NodeFactory.Node.GetCurrent();
var your21Happy = current.Parent.GetChildNodes().First(); // or the way you was getting it already.
var descendants = your21Happy.GetDescendantNodes();
uQuery is pretty flexible, you can filter queried nodes by anything, like
.GetDescendantNodesByType("uBlogsyPost")
or
.GetDescendantNodes(x => x.WriterName == "admin")
etc.

Linq To Xml - ReplaceNodes updates number of elements found in original query

I have a linq to xml query which returns 2 nodes. I am attempting to iterate over these nodes and replace their content. However the content that is being added to the XDocument contains nodes which match my query criteria.
protected internal virtual void AddLinkDocument(XDocument content, TaskRequest request)
{
var links = content.Descendants("some.link").Where(tag => tag.Attribute("document-href") != null);
foreach (XElement link in links) //first time through there are 2 links found
{
//do some stuff
link.ReplaceNodes(inlineContent); // after content is added, "links" now in foreach now has many new links found
}
}
Why is the collection, "links" being updated dynamically each time through the foreach?
Thanks for the help!
Seems like there are a few factors at play here:
The way you've defined links, it's going to be re-queried for each iteration of foreach.
The re-query will search for all descendants matching the query (not just immediate children).
My guess is that the iteration block adds some new elements that match the query (ie, contain a "document-href" attribute).
So, I'd suggest trying either:
adding a ToArray() to the end of the definition for links;
or using Elements instead of Descendants to query only the child nodes of content.

Fastest tree traversal

I have a pretty large tree data structure that will get updated (nodes removed and added, etc). I have to traverse the tree using breadth first approach to visit all the nodes (to a certain breadth depth like 7) and put it a to a list. Then a function will loop through the nodes and return true if an information was found inside of the list.
This is taking a lot of time to loop through the nodes. I don't think I should map every single node with every single children node and then pull the node using Dictionary and get all its children (recursively). How should I do this? The fastest way is to map all nodes between each other like
Dictionary<Node, List<Node>>
node, list of all children (including children of children...) and then pull the nodes and get its like 2,000 children fast. But if a node is added or removed anywhere, all the dictionary nodes need to be updated (which seems like a hassle). The other way is to dynamically loop through it during run (which takes time). It is a matter of mapping everything together in the beginning during tree generation, or looping during run time.
What is the best way to handle this situation? Any idea, pointers, comments, any thing is helpful. Currently this operation takes about 25% of the program run time.
If you are just evaluating a predicate you can do that directly while traversing the tree, you don't have to put the full tree into a list first - unless you cache the list. Evaluating the predicate on the the tree nodes directly, you can short circuit / stop traversing early when you first find the information you are interested in.

how to do a multiple selection from the databse using nhibernate?

I need to show the result of a multiple selection and do not know how I can handle, the problem is as follows:
I have a tree, which is multipleselection, selecting the first time, this shows me the correct information, but when I select another node, the information should be displayed for the first and the second selection, but only show the second.
My question is, how I can store the previous selection and link this with the new one ..? I'm working with NHibernate, C # and the MVC model.
I appreciate any help.
Sincerely
you can Query for multiple Selections
IEnumerable<Entity> results = Enumerable.Empty<Entity>();
foreach (var node in selectedNodes)
{
results = results.Concat(Session.Query<Entity>().Where(...).Future<Entity>());
}
Show(results);
Or cache the results of selections
Dictionary<node, IEnumerable<Entity>> _nodeResults; // somewhere
foreach (var node in selectedNodes)
{
if (!_nodeResults.ContainsKey(node))
_nodeResults.Add(node, Session.Query<Entity>().Where(...).Future<Entity>());
results = results.Concat(_nodeResults[node]);
}
if you need distinct results use Intersect instead of Concat or use Show(results.Distinct());

Categories

Resources