I have a list which contains order property of string.
This is what the data looks like:
1
2
2.1
2.1.1
2.1.2
2.2
2.2.1
2.2.2
3
3.1
3.2
3.3
4
And the structure of class is like this
public class CMNavBarDefaultDto
{
public int ID { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public string? Comments { get; set; }
public string Order { get; set; }
public bool ToShowGray { get; set; }
public bool IsNew { get; set; }
}
if the user delete any order from the list, like user delete 3.1 then 3.2 and 3.3 rearrange 3.2 become 3.1, 3.3 become 3.1, if the user delete any parent like 1 then all the hierarchy should be maintained in a new form like 2 become 1 and its child and sub-child should start from 1.
Can anyone suggest to me what approach is helpful in this scenario?
CodePudding user response:
Seems to me, best method is to use list of uint
s to specify level as needed. You could then parallel the html table with Order object to update table as needed by having delete operation actually modify Order, which then updates html table.
The question is what to do if user deletes middle level? For example, if user deletes 1.1 in the following order, what happens to 1.1.1 and 1.1.2?
1
1.1
1.1.1
1.1.2
1.2
Does it become like below?
1
1.1
1.2
1.3 (was 1.2)
Knowing these rules, you can create a conversion function to create parallel Order and then operate on it as needed. The below code assumes all prior levels are defined as you go deeper (i.e., if you have a level 2, it is assumed the prior level was 2 or 1). At any point you can jump up levels (i.e., you could be at level 4 and then have the next level 1). If you don't follow these rules, the ToString function would throw Exception.
public class Order
{
var list = new List<unit>();
// needed: static function or constructor that takes html table string and returns Order and methods to modify Order
public override string ToString()
{
var sb = new StringBuilder();
var stack = Stack<(uint, string))>();
uint current = 0;
string order = "";
foreach (var next in list)
{
if (next > stack.Count)
{
// next is in deeper level, make sure prior level(s) exist.
if ((current == 0) || (next != (stack.Count 1))) throw new Exception("missing level");
// prior level(s) exist, push current level in stack in case lower level needed later, then restart count within next level
stack.Push((current, order));
order = $"{order}{current}.";
current = 0;
}
else if (next < stack.Count)
{
// at lower level! pop out levels from stack until we get back to next level
while (stack.Count > next)
{
(current, order) = stack.Pop();
}
}
// append next level to output
current ;
sb.AppendLine($"{order}{current}");
}
return sb.ToString();
}
}
CodePudding user response:
The following will create the tree. You have to add code to do add and remove items in tree. When you add or remove you have to renumber the items
using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
List<CMNavBarDefaultDto> list = new List<CMNavBarDefaultDto>()
{
new CMNavBarDefaultDto() { Order = "1"},
new CMNavBarDefaultDto() { Order = "2"},
new CMNavBarDefaultDto() { Order = "2.1"},
new CMNavBarDefaultDto() { Order = "2.1.1"},
new CMNavBarDefaultDto() { Order = "2.1.2"},
new CMNavBarDefaultDto() { Order = "2.2"},
new CMNavBarDefaultDto() { Order = "2.2.1"},
new CMNavBarDefaultDto() { Order = "2.2.2"},
new CMNavBarDefaultDto() { Order = "3"},
new CMNavBarDefaultDto() { Order = "3.1"},
new CMNavBarDefaultDto() { Order = "3.2"},
new CMNavBarDefaultDto() { Order = "3.3"},
new CMNavBarDefaultDto() { Order = "4"},
};
Tree root = new Tree();
root.MakeTree(list, root);
}
}
public class CMNavBarDefaultDto
{
public int ID { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public string? Comments { get; set; }
public string Order { get; set; }
public bool ToShowGray { get; set; }
public bool IsNew { get; set; }
}
public class Tree
{
public CMNavBarDefaultDto cmNav { get; set; }
public int[] orderInt { get; set; }
public List<Tree> children { get; set; }
public void MakeTree(List<CMNavBarDefaultDto> cmNavs, Tree parent)
{
List<Tree> list = new List<Tree>();
foreach(CMNavBarDefaultDto cmNav in cmNavs)
{
Tree node = new Tree() { cmNav = cmNav, orderInt = cmNav.Order.Split(new char[] { '.' }).Select(x => int.Parse(x)).ToArray() };
list.Add(node);
}
int level = 0;
list = list.OrderBy(x => x.orderInt.Length).ToList();
MakeTreeRecursive(list, parent, level);
}
public void MakeTreeRecursive(List<Tree> list, Tree parent, int level)
{
var groups = list.GroupBy(x => x.orderInt[level]).ToList();
foreach(var group in groups)
{
if (parent.children == null) parent.children = new List<Tree>();
parent.children.Add(group.First());
if (group.Count() > 1)
{
if (group.Last().orderInt.Length == level 1)
{
group.First().children = new List<Tree>();
group.First().children = group.Skip(1).ToList();
}
else
{
MakeTreeRecursive(group.Skip(1).ToList(), group.First(), level = 1);
}
}
}
}
}
}