I have a List (.NET) and need to build an indented tree structure. Each item in the list has a Position property indicating the level of indentation. The final structure should look something like this:
// (1) 1
// (2) 1-1
// (2) 1-2
// (2) 1-3
// (1) 2
// (2) 2-1
// (3) 2-1-1
// (1) 3
The number inside the parentheses is the Position property. Each subsequent item at a given level should have a label indicated its count in the list of items at that level. Lower position levels will have sort of an outline format label, as shown in the sample. Keep in mind, I have to generate those labels correctly.
I honestly haven't done recursive work for a while and, although I'm thinking that will be the best solution, I'm just stuck on how to get the job done. I may be over-complicating it. My thinking is that when I get to a "leaf," I should remove that item from the list and return, but I'm not sure. Just spinning my wheels a bit.
Thanks, Jay
UPDATE:
Here's something close, but I'm having trouble figuring out the last case. So far, it does fine if the next item falls on the same level or is indented one level, but I need a case for when the next item in the list is in a position less than the current one (i.e., is indented farther to the left). Also, I'm not sure about my base case at the top of the method:
var sb = new StringBuilder();
BuildTree(sb, list, 0, 1, string.Empty);
return sb.ToString();
private void BuildTree(StringBuilder sb, List<Item> list, int currIndex, int count, string parentId)
{
if (list.Count == currIndex)
{
return;
}
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
}
UPDATE:
An alternative implementation, but still failing for the case of a less-indented row:
private void BuildTree(StringBuilder sb, List<Item> list, int currIndex, int count, string parentId)
{
if (list.Count == 0)
{
return;
}
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
list.RemoveAt(currIndex);
}
UPDATE:
This is a hack, but it works. I'm basically building multiple sub-trees off the root. I'd prefer a proper solution rather than a hack, but this is my best attempt so far. Alternatives welcome:
var sb = new StringBuilder();
List<Person> list = GetTheList();
int cnt = 0;
while (list.Count > 0)
{
BuildTree(sb, list, 0, ++cnt, string.Empty);
}
return sb.ToString();
private void BuildTree(StringBuilder sb, List<Person> list, int currIndex, int count, string parentId)
{
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list.Count > 1)
{
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
}
list.RemoveAt(currIndex);
}