I am looking for a better way of sorting the following type of data. The below works fine for smaller data sets (on some systems its 2000 on other 9000) but causes a stackoverflow when processing larger ones
The structure in place that holds the data looks like this
public class AttributeItem
{
public string AttributeType { get; set; }
public string Title { get; set; }
public string Value { get; set; }
public int ObjectID { get; set; }
public bool CanModify { get; set; }
public bool CanDelete { get; set; }
public bool? IsParent { get; set; }
public int SortID { get; set; }
public int? ParentSortID { get; set; }
public bool Deleted { get; set; }
}
public class AttributeItemNode
{
public AttributeItem Item {get;set;}
public int Depth {get;set;}
public AttributeItemNode(AttributeItem item , int Depth)
{
this.Item = item ;
this.Depth = Depth;
}
}
Here is an example of the data needing to be sorted into a single object with an int indicating their depth. It is possible for the children levels to go deeper than the three level shown in the example data
var items = new List<AttributeItem>();
items.Add(new AttributeItem{Title ="Parent1", ObjectID=1,SortID =1, IsParent= true, ParentSortID = Int32.MinValue});
items.Add(new AttributeItem{Title ="FooChild", ObjectID=2,SortID =2, IsParent= false, ParentSortID = 1});
items.Add(new AttributeItem{Title ="Parent2", ObjectID=4,SortID =4, IsParent= true, ParentSortID = Int32.MinValue});
items.Add(new AttributeItem{ Title ="Parent2Child1", ObjectID=5,SortID =5, IsParent= false, ParentSortID = 4});
items.Add(new AttributeItem{Title ="Parent2Child2", ObjectID=7,SortID =7, IsParent= false, ParentSortID = 4});
items.Add(new AttributeItem{Title ="Parent2Child2Child1", ObjectID=6,SortID =6, IsParent= false, ParentSortID = 5});
The expected output would be as follows (I have removed the irrelevant data from the object to help readability)
Depth = 0 Title ="Parent1"
Depth = 1 Title ="FooChild"
Depth = 0 Title ="Parent2"
Depth = 1 Title ="Parent2Child1"
Depth = 2 Title ="Parent2Child2Child1"
Depth = 1 Title ="Parent2Child2"
Here is the actual sorting code
public static IList<AttributeItemNode> SortAttributeItems(IList<AttributeItem> list)
{
List<AttributeItemNode> newList = new List<AttributeItemNode>();
SortAttributeItems(list, null, 0, newList);
return newList;
}
private static void SortAttributeItems(IList<AttributeItem> list, AttributeItem currentItem, int depth, List<AttributeItemNode> newList)
{
AttributeItem newItem = null;
// look for children
if (currentItem != null)
{
foreach (AttributeItem item in list)
{
if (item.ParentSortID.HasValue && item.ParentSortID.Value != Int32.MinValue && item.ParentSortID.Value == currentItem.SortID)
{
newList.Add(new AttributeItemNode(item, (depth + 1)));
SortAttributeItems(list, item, depth + 1, newList);
}
}
}
if (depth == 0)
{
foreach (AttributeItem item in list)
{
if (!item.ParentSortID.HasValue || item.ParentSortID.Value == Int32.MinValue)
{
if (currentItem == null || item.SortID >= currentItem.SortID)
{
if (newItem == null || newItem.SortID >= item.SortID)
{
newItem = item;
}
}
}
}
}
if (newItem != null)
{
newList.Add(new AttributeItemNode(newItem, depth));
list.Remove(newItem);
SortAttributeItems(list, newItem, depth, newList);
}
}