遍历列表以确定元素的层次结构级别

Iterate throuh list to determine hierarchy level of elements

有一个项目列表,其中包含一个名为 "HierarchyLevel" 的字段(String 的类型),它确定元素的层次结构,如下所示:Link to image . 树结构如下所示:

<ul>
<li>1</li>
<ul>
<li>1.01</li>
<ul>
<li>1.01.01</li>
<li>1.01.02</li>
</ul>
<li>1.02</li>
<ul>
<li>1.02.01</li>
</ul>
<li>1.03</li>
</ul>
<ul>

以此类推

我的目标是实现一个 class,其中包含有关每个元素的父项和子项的信息。 到目前为止我有这个 class:

class TreeNode<DBItem>
{
    public DBItem Value { get; private set; }
    public List<TreeNode<DBItem>> Children = new List<TreeNode<DBItem>>();
    public TreeNode<DBItem> Parent { get; private set; }

    public string Level { get; private set; }

    public TreeNode (DBItem item, string level)
    {
        this.Value = item;
        this.Level = level;
    }

    public TreeNode<DBItem> this[int i]
    {
        get { return this.Children[i]; }
    }

    public TreeNode<DBItem> AddChild(DBItem item, string level)
    {
        TreeNode<DBItem> node = new TreeNode<DBItem>(item, level) { Parent = this };
        this.Children.Add(node);
        return node;
    }
 }

问题是我不太明白如何遍历项目集合。我试过这个:

TreeNode<DBItem> parent = new TreeNode<DBItem>(neededItems[0], "1");
foreach (var doc in neededItems)
{
    string level = doc.GetStringValue("HierarchyLevel");
    if (level.StartsWith("1.")&& level.Length < 5)
    {
        var child1 = parent.AddChild(doc, level);
        foreach (var child in neededItems)
        {
            string level1 = child.GetStringValue("HierarchyLevel");
            if (level1.StartsWith("1."+level))
            {
                child1.AddChild(child, level1);
            }
        }
    }
}

但显然这是一种糟糕的做法。 我想获得一些关于如何正确遍历列表的帮助和建议。

我们可以使用:

  • 所有项目的字典(帮助查找父节点)
  • a 根节点列表(如果有超过 1 个根)
  • 按层次结构深度排序的 DBItem 对象列表(1.01 之前为 1)

实施示例:

class so43271922
{
    public so43271922()
    {
    }

    [DebuggerDisplay("HierarchyLevel = {HierarchyLevel}")]
    public class DBItem
    {
        public string Name { get; private set; }
        public string HierarchyLevel { get; private set; }

        public DBItem(string name, string hierarchyLevel)
        {
            this.Name = name;
            this.HierarchyLevel = hierarchyLevel;
        }
    }

    // Dummy list of DB Item objects
    public readonly DBItem[] listItems = new DBItem[] {
        new DBItem("Element 1", "1"),
        new DBItem("Element 1.01", "1.01"),
        new DBItem("Element 1.01.01", "1.01.01"),
        new DBItem("Element 1.01.02", "1.01.02"),
        new DBItem("Element 1.02", "1.02"),
        new DBItem("Element 1.02.01", "1.02.01"),
        new DBItem("Element 1.03", "1.03")
    };

    [DebuggerDisplay("HierarchyLevel = {Value.HierarchyLevel}")]
    public class Node
    {
        public static IReadOnlyDictionary<string,Node> AllNodes { get { return allNodes; } }
        public static IReadOnlyCollection<Node> Roots { get { return roots; } }

        /// <summary>
        /// Stores references to all nodex, using HierarchyLevel as key
        /// </summary>
        private static Dictionary<string, Node> allNodes = new Dictionary<string, Node>();
        /// <summary>
        /// Stores references to root nodes
        /// </summary>
        private static List<Node> roots = new List<Node>();



        public DBItem Value { get; private set; }
        public Node Parent { get; private set; }
        public List<Node> Children { get; private set; }

        public int Level { get; private set; }

        public Node(DBItem li)
        {
            this.Children = new List<Node>();
            this.Value = li;
            allNodes.Add(li.HierarchyLevel, this);

            if (li.HierarchyLevel.Contains("."))
            {
                var parentHier = li.HierarchyLevel.Substring(0, li.HierarchyLevel.LastIndexOf("."));
                this.Parent = allNodes[parentHier];
                this.Parent.Children.Add(this);
                this.Level = this.Parent.Level + 1;
            }
            else
            {
                roots.Add(this);
                this.Parent = null;
                this.Level = 0;
            }
        }
    }

    public void generateHierarchy()
    {
        // Sort all items by: hierarchy depth, then by hierarchy level value
        var sortedItems = listItems
            .OrderBy(i => i.HierarchyLevel.Count(c => c == '.')); // 1 before 1.01

        foreach (var item in sortedItems)
        {
            new Node(item);
        }

        var hier = Node.Roots;
    }

}