代码之家  ›  专栏  ›  技术社区  ›  lem.mallari

从c中的平面列表创建嵌套列表#

  •  4
  • lem.mallari  · 技术社区  · 6 年前

    我目前有以下课程:

    public class NavigationItem
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public int ParentID { get; set; }
        public List<NavigationItem> Children { get; set; }
    }
    
    public class FlatItem
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public int ParentID { get; set; }
    }
    

    我有一个样本数据如下:

    +====+============+==========+
    | ID |   Title    | ParentID |
    +====+============+==========+
    |  1 | Google     |          |
    +----+------------+----------+
    |  2 | Microsoft  |          |
    +----+------------+----------+
    |  3 | Oracle     |          |
    +----+------------+----------+
    |  4 | Gmail      |        1 |
    +----+------------+----------+
    |  5 | Sheets     |        1 |
    +----+------------+----------+
    |  6 | Adsense    |        1 |
    +----+------------+----------+
    |  7 | Azure      |        2 |
    +----+------------+----------+
    |  8 | SharePoint |        2 |
    +----+------------+----------+
    |  9 | Office     |        2 |
    +----+------------+----------+
    | 10 | Java       |        3 |
    +----+------------+----------+
    | 11 | Word       |        9 |
    +----+------------+----------+
    | 12 | Excel      |        9 |
    +----+------------+----------+
    | 13 | PowerPoint |        9 |
    +----+------------+----------+
    

    我已经有了从上面的示例数据中提取所有信息并将其转换为 List<FlatItem> 对象。

    最好的方法是什么? List<NavigationItem> 对象,其外观如下所示:

    • 谷歌
      • Gmail
      • 希茨
      • AdSense
    • 微软
      • 蔚蓝
      • 共享点
      • 办公室
        • 擅长
        • 幻灯片演示文稿软件
    • 甲骨文公司
      • 爪哇

    我正在考虑创建一个递归方法来遍历 列表<扁平项> 然后将其结构为一个导航项的嵌套列表。

    4 回复  |  直到 6 年前
        1
  •  2
  •   ViRuSTriNiTy    6 年前

    不需要递归。可以使用linq轻松构建结构:

    List<FlatItem> flatItems = ...;
    
    var navigationItems = flatItems.Select(
        i => new NavigationItem { ID = i.ID, Title = i.Title, ParentID = i.ParentID }
    ).ToList();
    
    foreach (var i in navigationItems)
        i.Children = navigationItems.Where(n => n.ParentID == i.ID).ToList();
    
    // get Google, Microsoft, Oracle items
    var rootNavigationItems = navigationItems.Where(n => n.ParentID == 0);
    
        2
  •  1
  •   TheGeneral    6 年前

    未经测试,但你可以试试这个,应该也相当快

    var list = new List<FlatItem>();
    var result = new List<NavigationItem>();
    
    // just a helper to remember ids
    var dict = new Dictionary<int, NavigationItem>();
    
    foreach (var item in list)
    {
       var nav = new NavigationItem()
                      {
                         ID = item.ID,
                         ParentID = item.ParentID,
                         Title = item.Title,
                         Children = new List<NavigationItem>()                                   
                      };
    
       if (!dict.ContainsKey(nav.ParentID))
          result.Add(nav);       
       else
          dict[nav.ParentID].Children.Add(nav);
    
       dict.Add(item.ID, nav);
    }
    
        3
  •  1
  •   Konamiman    6 年前

    如果可以使用递归,则可以创建如下函数:

    public List<NavigationItem> ChildrenOf(List<FlatItem> flatItems, int parentId)
    {
        var childrenFlatItems = flatItems.Where(i => i.ParentID == parentId);
        return childrenFlatItems.Select(i => new NavigationItem {
            ID = i.ID,
            Title = i.Title,
            ParentID = i.ParentID, 
            Children = ChildrenOf(flatItems, i.ID)})
        .ToList();
    }
    

    然后,假设您的根项的父ID为0(因为您没有使用可为空的类型),您将生成包含以下内容的完整列表:

    ChildrenOf(flatsItems, 0)
    
        4
  •  1
  •   Enigmativity    6 年前

    试试这个:

    List<FlatItem> source = new List<UserQuery.FlatItem>()
    {
        new FlatItem() { ID = 1, Title = "Google", ParentID = null },
        new FlatItem() { ID = 2, Title = "Microsoft", ParentID = null },
        new FlatItem() { ID = 3, Title = "Oracle", ParentID = null },
        new FlatItem() { ID = 4, Title = "Gmail", ParentID = 1 },
        new FlatItem() { ID = 5, Title = "Sheets", ParentID = 1 },
        new FlatItem() { ID = 6, Title = "Adsense", ParentID = 1 },
        new FlatItem() { ID = 7, Title = "Azure", ParentID = 2 },
        new FlatItem() { ID = 8, Title = "SharePoint", ParentID = 2 },
        new FlatItem() { ID = 9, Title = "Office", ParentID = 2 },
        new FlatItem() { ID = 10, Title = "Java", ParentID = 3 },
        new FlatItem() { ID = 11, Title = "Word", ParentID = 9 },
        new FlatItem() { ID = 12, Title = "Excel", ParentID = 9 },
        new FlatItem() { ID = 13, Title = "PowerPoint", ParentID = 9 },
    };
    
    var lookup = source.ToLookup(x => x.ParentID);
    
    Func<int?, List<NavigationItem>> build = null;
    build = pid =>
        lookup[pid]
            .Select(x => new NavigationItem()
            {
                ID = x.ID,
                Title = x.Title,
                ParentID = x.ParentID,
                Children = build(x.ID)
            })
            .ToList();
    

    启动进程调用 build(null) . 这让我想到:

    Tree

    这确实假设 ParentId 财产是 int? -你的数据表确实建议。