【问题标题】:How to build a tree node relation ship using linq ( non-binary tree如何使用 linq(非二叉树)构建树节点关系
【发布时间】:2014-08-02 05:46:15
【问题描述】:

我有一个具有以下结构的类

public class Menu
{
    public Menu()
    {
        ChildMenus = new List<Menu>();
    }

    public string MenuName { get; set; }
    public int Id { get; set; }
    public int Level { get; set; }
    public int Order { get; set; }
    public string RefCode { get; set; }
    public List<Menu> ChildMenus { get; set; }
    public int ParentId { get; set; }
}

以及菜单对象的集合,例如:

public class MenuManager
{
    public List<Menu> Menucollection;

    public MenuManager()
    {
        Menucollection = new List<Menu>
        {
            new Menu {MenuName = "Products", Id = 1, ParentId = 0, Level = 1, RefCode = "0", Order = 1},
            new Menu {MenuName = "Sales", Id = 2, ParentId = 0, Level = 1, RefCode = "0", Order = 2},
            new Menu {MenuName = "Contacts", Id = 3, ParentId = 0, Level = 1, RefCode = "0", Order = 3},
            new Menu {MenuName = "Mobiles", Id = 4, ParentId = 1, Level = 2, RefCode = "0", Order = 1},
            new Menu {MenuName = "Computers", Id = 5, ParentId = 1, Level = 2, RefCode = "0", Order = 2},
            new Menu {MenuName = "Local Sales", Id = 6, ParentId = 2, Level = 2, RefCode = "0", Order = 1},
            new Menu {MenuName = "Forgin Sales", Id = 7, ParentId = 2, Level = 2, RefCode = "0", Order = 2},
            new Menu {MenuName = "Email", Id = 8, ParentId = 3, Level = 2, RefCode = "100", Order = 1},
            new Menu {MenuName = "Nokia", Id = 9, ParentId = 4, Level = 3, RefCode = "110", Order = 1},
            new Menu {MenuName = "LG", Id = 10, ParentId = 4, Level = 3, RefCode = "111", Order = 2},
            new Menu {MenuName = "Accer", Id = 11, ParentId = 5, Level = 3, RefCode = "210", Order = 1},
            new Menu {MenuName = "Kerala", Id = 9, ParentId = 6, Level = 3, RefCode = "110", Order = 1}
        };
    }

    public void BuildMenu()
    {
    }
}

我需要从集合中构建一个菜单结构,条件如下:

在以下情况下必须删除菜单项:

  1. 如果它没有任何孩子。
  2. 如果它的 refcode 等于 0。

所以基于输入的预期结果应该是:

Product    Sales         Contact
Mobile     Local Sales   Email
Nokia      Kerala
LG
Computer 
Accer                

【问题讨论】:

  • linq 中没有递归,尽管您可以编写自己的递归扩展方法
  • 所以没有设置 ChildMenu 属性,您想根据 RefCodes 填充它们吗?
  • 你为什么有“ids”。这不是数据库。改用引用。

标签: c# asp.net .net linq


【解决方案1】:

首先,与前面的注释相反,递归不需要处理树。它通常是最简单、最简单的方法(顺便说一下,我提供的方法)——但不是必需的(有时出于性能原因需要避免递归)。

注意,扩展方法是基于我从这里偷的一个片段:Searching a tree using LINQ

            var filteredMenus = from m in Menucollection
                                where m.RefCode != "0" || Menucollection.Any(m1=>m1.ParentId == m.Id)
                                select m;

            foreach(var m in filteredMenus)
            {
                m.ChildMenus = filteredMenus.Where(m1=>m1.ParentId == m.Id).ToList();
            }

            var expanded = from m in filteredMenus
                       where m.ParentId == 0
                       select new { Menu = m, Descendants = m.AsBreadthFirstEnumerable(m1 => m1.ChildMenus) };

            foreach (var m in expanded)
            {
                System.Diagnostics.Debug.WriteLine("Menu: " + m.Menu.MenuName);
                foreach (var m1 in m.Descendants)
                {
                    System.Diagnostics.Debug.WriteLine("- " + m1.MenuName);
                }
            }

然后在一些静态类中:

    public static IEnumerable<T> AsBreadthFirstEnumerable<T>(this T head, Func<T, IEnumerable<T>> childrenFunc)
    {
        yield return head;

        var last = head;
        foreach (var node in AsBreadthFirstEnumerable(head, childrenFunc))
        {
            foreach (var child in childrenFunc(node))
            {
                yield return child;
                last = child;
            }
            if (last.Equals(node)) yield break;
        }
    }

它不是纯粹的 LINQ - 但它应该为您提供一些可以开始的东西。

【讨论】:

    猜你喜欢
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多