在C#中使用平面列表创建嵌套列表

时间:2018-06-05 10:19:45

标签: c# .net

我目前有以下课程:

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
  • 微软
    • 天青
    • 的SharePoint
    • 办公
      • Excel中
      • 的PowerPoint
  • 甲骨文
    • 爪哇

我正在考虑创建一个递归方法来遍历我的List<FlatItem>,然后以一种嵌套的NavigationItem列表的方式构造它。

5 个答案:

答案 0 :(得分:2)

无需递归。您可以使用LINQ轻松构建结构:

<ListView x:Name="lvRitten" Grid.Column="0" Background="Gold" ItemsSource="{Binding ObcRitten}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionChanged="lvRitten_SelectionChanged" SelectionMode="Single">
    <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type classes:Rit}">
            <Button x:Name="btnride" Height="100" Width="132" >
                <StackPanel>
                    <Grid Height="100" Width="132">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="1*"/>
                            <RowDefinition Height="3*"/>
                        </Grid.RowDefinitions>
                        <Grid Grid.Row="0" Grid.ColumnSpan="2" Background="Aquamarine">
                            <Label Content="naam"/>
                        </Grid>
                        <Grid Grid.Column="0" Grid.Row="1" Background="AntiqueWhite">
                            <StackPanel>
                                <Label Content="{Binding id}" FontSize="10"/>
                                <Label Content="{Binding Naam}" FontSize="10"/>
                                <Label Content="{Binding AantalPassagiers}" FontSize="10"/>
                                <Label Content="{Binding TaxiNummer}" FontSize="10"/>
                            </StackPanel>
                        </Grid>
                        <Grid Grid.Column="1" Grid.Row="1">

                        </Grid>
                    </Grid>
                </StackPanel>
            </Button>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

答案 1 :(得分:1)

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

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);
}

答案 2 :(得分:1)

试试这个:

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? - 您的数据表确实建议。

答案 3 :(得分:1)

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

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 :(得分:0)

无需递归,只需GroupBy

List<NavigationItem> list = ... // map from List<FlatItem> 
// and init Children = new List<NavigationItem>();

var groups = list.GroupBy(x => x.ParentID).ToList();
foreach (var g in groups)
{
    var items = list.Find(x => x.ID == g.Key);
    if (items != null) 
        items.Children = g.ToList();
}

// tops is [Google, Microsoft, Oracle]
var tops = list.Where(x => x.ParentID == null).ToList();