Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Inspired by your input -- and thanks for that -- I came up with a solution. I create a tree of all possible combinations. The root of the tree is the first item in the list of objects. My tree handler class calls itself recursively to loop trough the objects. At the leaf node, I check for a intersection of periods of all the nodes in the path. If there is an intersecting period, I have a valid combination, and the treehandler passes that on throug a delegate. If the path does not have an intersecting period, it cannot be used. I have excluded secondary classes, but i can insert them, if you request it: </p> <pre><code>internal delegate void PathDelivery(JPTreeNode treeNode, Period periodInCommon); //Deliver a path through this delegate internal class TreeHandler //The main class { private readonly PathDelivery _pathDelivery; // Construct with public TreeHandler(PathDelivery pathDelivery) { _pathDelivery = pathDelivery; } public void HandleNode(IList&lt;SourceRow&gt; jpSource, int level,JPTreeNode parentNode, Period intersectingPeriod) { int sequenceId = level + 1; IList&lt;SourceRow&gt; children = new List&lt;SourceRow&gt;(System.Linq.Enumerable.Where(jpSource, S =&gt; S.Id == sequenceId)); if (children.Count == 0) //The last leaf level... return the path throug PathDelivery delegate if valid dates { if (intersectingPeriod!= null) _pathDelivery(parentNode, intersectingPeriod); //Only deliver this path if all nodes in path has an intersecting period } else //This node has children to add { foreach (SourceRow child in children) //Loop and create children { Stop stop = new Stop(child.Id, child.Period, child.Description); //Value object for child node //Re-calculate the valid period (intersect) for the tree path Period newIntersect = Period.Intersect(stop.Period, intersectingPeriod); JPTreeNode childNode = new JPTreeNode(parentNode, stop); //Create the child node if (parentNode!= null) //If not at root level, add child node to parent node parentNode.ChildNodes.Add(childNode); // Recursive call, handle possible grandchildren (children of this childNode) or finish path HandleNode(jpSource, sequenceId, childNode, newIntersect); } } } } </code></pre> <p>Below is a unit test fixture that demonstrates the use: </p> <pre><code>[TestFixture] public sealed class TestRecursiveDataHandling { private IList&lt;Path&gt; _pathList; [SetUp] public void SetUp() { _pathList = new List&lt;Path&gt;(); } [TearDown] public void TearDown() { _pathList = null; } [Test] public void CreateLists() { //Create the data source IList&lt;SourceRow&gt; jpSource = new List&lt;SourceRow&gt;(); jpSource.Add(new SourceRow("1", 1, new DateTime(2000, 1, 1), new DateTime(2009, 12, 31))); jpSource.Add(new SourceRow("2A", 2, new DateTime(2000, 1, 1), new DateTime(2004, 12, 31))); jpSource.Add(new SourceRow("2B", 2, new DateTime(2005, 1, 1), new DateTime(2009, 12, 31))); jpSource.Add(new SourceRow("3", 3, new DateTime(2000, 1, 1), new DateTime(2009, 12, 31))); jpSource.Add(new SourceRow("4A", 4, new DateTime(2000, 1, 1), new DateTime(2008, 12, 31))); jpSource.Add(new SourceRow("4B", 4, new DateTime(2009, 1, 1), new DateTime(2009, 12, 31))); //Instantiate handler TreeHandler handler = new TreeHandler(CreatePathFromButtonNode); //Handle root node, and recurse handler.HandleNode(jpSource, 0, null, Period.Infinite); //DISPLAY TREE PATHS IN CONSOLE DisplayResultInConsole(); //A simple assertion. Expect that 3 paths were created. Assert.That(_pathList.Count, Is.EqualTo(3)); } private void DisplayResultInConsole() { for (int i = 0; i &lt; _pathList.Count; i++ ) { IList&lt;Stop&gt; jpList = _pathList[i].Stops; string stopList = string.Empty; foreach (Stop stop in jpList) { stopList = stopList + stop.ID + ";" + stop.Description + ";"+ stop.Period + " \n"; } string p = "List " + i + "&gt;&gt; Period " + _pathList[i].Period; Console.WriteLine("List " + i + "&gt;&gt; Period " + p); Console.WriteLine("Stops: "); Console.WriteLine(stopList); Console.WriteLine(); } } //Method for receiving paths from leaf nodes. Passed as delegate to TreeHandler private void CreatePathFromButtonNode(JPTreeNode treeNode, Period periodInCommon) { IList&lt;Stop&gt; stopList = new List&lt;Stop&gt;(); JPTreeNode currentNode = treeNode; while (currentNode!= null) { stopList.Add(currentNode.NodeValue); currentNode = currentNode.ParentNode; } _pathList.Add(new Path(periodInCommon, stopList)); } } </code></pre> <p>This test generates the following output to Console. Note that the path (combination) 4B;3;2A;1 has not been returned. This is because the periods of 2A and 4B does not intersect: </p> <p>List 0>> Period List 0>> Period From: 1/1/2000 To: 12/31/2004<br> Stops:<br> 4;4A;From: 1/1/2000 To: 12/31/2008<br> 3;3;From: 1/1/2000 To: 12/31/2009<br> 2;2A;From: 1/1/2000 To: 12/31/2004<br> 1;1;From: 1/1/2000 To: 12/31/2009 </p> <p>List 1>> Period List 1>> Period From: 1/1/2005 To: 12/31/2008<br> Stops:<br> 4;4A;From: 1/1/2000 To: 12/31/2008<br> 3;3;From: 1/1/2000 To: 12/31/2009<br> 2;2B;From: 1/1/2005 To: 12/31/2009<br> 1;1;From: 1/1/2000 To: 12/31/2009 </p> <p>List 2>> Period List 2>> Period From: 1/1/2009 To: 12/31/2009 Stops:<br> 4;4B;From: 1/1/2009 To: 12/31/2009<br> 3;3;From: 1/1/2000 To: 12/31/2009<br> 2;2B;From: 1/1/2005 To: 12/31/2009<br> 1;1;From: 1/1/2000 To: 12/31/2009 </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload