【问题标题】:Recursive menu is wrong level ordered递归菜单的顺序错误
【发布时间】:2020-04-28 07:29:35
【问题描述】:

尝试使用 C# 构建递归菜单。我需要的菜单如下:

。客户
. . . .客户 1
. . . .客户 3
.公司
. . . .愿景
. . . . . . .简短陈述
. . . .我们是谁
. . . . . . .联系我们
. . . . . . .团队
. . . . . . . . . .写信给我们
. . . . . . . . . . . . .媒体

但我得到了:

。公司
. . . .愿景
. . . .我们是谁
. . . . . . .简短陈述
. . . . . . . . . .联系我们
. . . . . . . . . .团队
. . . . . . . . . . . . .写信给我们
. . . . . . . . . . . . . . . .媒体
.客户
. . . .客户 1
. . . .客户 3

需要进行一些更正,因此我需要您的帮助:

  • 菜单项应按字母顺序排列;前任。客户首先是公司
  • 某些项目的排序和缩进级别错误;前任。简短的陈述应该在愿景之后和我们是谁之前

到目前为止我尝试过:

class Program
{
    public class Node<T>
    {
        public T Data { get; set; }
        public List<Node<T>> Children { get; set; }

        public Node()
        {
            Children = new List<Node<T>>();
        }


        public List<Node<T>> LevelOrder()
        {
            List<Node<T>> list = new List<Node<T>>();
            Queue<Node<T>> queue = new Queue<Node<T>>();
            queue.Enqueue(this);
            while (queue.Count != 0)
            {
                Node<T> temp = queue.Dequeue();
                foreach (Node<T> child in temp.Children)
                    queue.Enqueue(child);
                list.Add(temp);
            }
            return list;
        }

        public List<Node<T>> PreOrder()
        {
            List<Node<T>> list = new List<Node<T>>();
            list.Add(this);
            foreach (Node<T> child in Children)
                list.AddRange(child.PreOrder());
            return list;
        }

        public List<Node<T>> PostOrder()
        {
            List<Node<T>> list = new List<Node<T>>();
            foreach (Node<T> child in Children)
                list.AddRange(child.PreOrder());
            list.Add(this);
            return list;
        }
    }

    public class Entity
    {
        public int id { get; set; }
        public string menuName { get; set; }
        public int? parentID { get; set; }
        public bool isHidden { get; set; }
        public string linkURL { get; set; }
    }
    static void Main(string[] args)
    {
        var data = @"ID;MenuName;ParentID;isHidden;Link
1;Company;NULL;False;/company
2;Who We Are;1;False;/company/whoweare
3;Vision;1;False;/company/vision
4;Team;2;False;/company/whoweare/team
5;Client 3;10;False;/clients/client3
6;Client 1;10;False;/clients/client1
7;Client 4;10;True;/clients/client4
8;Client 5;10;True;/clients/client5
10;Clients;NULL;False;/clients
11;Contact Us;2;False;/company/whoweare/contactus
12;Write To Us;4;False;/company/whoweare/team/writetous
13;Media;12;False;/company/whoweare/team/writetous/media
14;Short Statement;3;False;/company/vision/shortstatement";

        var lines = data.Split('\n');
        var rootNodes = new List<Node<Entity>>();
        var childItems = new List<Entity>();

        foreach (var row in lines.Skip(1))
        {
            var columns = row.Split(';');

            var id = Convert.ToInt32(columns[0]);
            var menuName = columns[1];
            var parentID = ToNullableInt(columns[2]);
            var isHidden = Convert.ToBoolean(columns[3]);
            var linkURL = columns[4];

            var entity = new Entity()
            {
                id = id,
                menuName = menuName,
                parentID = parentID,
                isHidden = isHidden,
                linkURL = linkURL
            };

            if (parentID == null)
            {
                rootNodes.Add(new Node<Entity>()
                {
                    Data = entity
                });
            }
            else
            {
                childItems.Add(entity);
            }
        }


        foreach (var rootNode in rootNodes)
        {
            foreach (var childItem in childItems.OrderBy(a => a.parentID).ThenBy(b => b.menuName))
            {
                var newNode = new Node<Entity>()
                {
                    Data = childItem
                };

                Insert(rootNode, newNode);
            }
        }

        foreach (var rootNode in rootNodes)
        {
            var indent = 0;
            var previous = rootNode;
            foreach (var node in rootNode.LevelOrder())
            {
                if (node.Data.isHidden) continue;

                if (previous.Data.parentID != node.Data.parentID)
                    indent++;

                for (var i = 0; i < indent; i++)
                    Console.Write(". . . ");

                Console.WriteLine(". " + node.Data.menuName);
                previous = node;
            }
        }
    }

    public static void Insert(Node<Entity> rootNode, Node<Entity> targetNode)
    {
        foreach (var current in rootNode.LevelOrder())
        {
            if (current.Data.id == targetNode.Data.parentID)
            {
                current.Children.Add(targetNode);
                return;
            }
        }
    }

    public static int? ToNullableInt(string s)
    {
        int i;
        if (int.TryParse(s, out i)) return i;
        return null;
    }
}

【问题讨论】:

  • 这样处理有什么具体原因吗?我的意思是,我认为在实体中保存序数可能更容易,因此您不需要每次都进行所有这些排序和排序。这对你来说可能吗?
  • 没有特别需要@ShaiBarak,我必须得到我的问题中的菜单

标签: c# list tree nodes recursive-datastructures


【解决方案1】:

如果您更新 PreOrder 以使用 (level, item) 的元组,例如:

        public List<(int level, Node<T> item)> PreOrder(int level = 0)
        {
            List<(int level, Node<T> item)> list = new List<(int level, Node<T> item)>();
            list.Add((level, this));
            level += 1;
            foreach (Node<T> child in Children)
                list.AddRange(child.PreOrder(level));
            return list;
        }

并在您的打印部分使用它(我还在这里添加了 menuName 的订单):

        foreach (var rootNode in rootNodes.OrderBy(a => a.Data.menuName))
        {
            var indent = 0;
            foreach (var node in rootNode.PreOrder())
            {
                if (node.item.Data.isHidden)
                    continue;

                for (var i = 0; i < node.level; i++)
                    Console.Write(". . . ");

                Console.WriteLine(". " + node.item.Data.menuName);
            }
        } 

这将以您请求的相同格式返回菜单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    相关资源
    最近更新 更多