C#如何从列表中删除特定节点

时间:2017-02-09 20:02:22

标签: c# list traversal removechild

我有以下课程

public class Item
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Content { get; set; }
    public bool IsLastItem { get; set; }
}

假设我有以下型号,我想删除IsLastItem = false并且没有孩子的项目。在这种情况下,item4和item7应该从列表中删除。

Model

我从数据库中获取了我的模型列表,并在代码块中模拟了它,就像这样

var items = new List<Item>
{
    new Item
    {
        Id = 1,
        ParentId = 0,
        Content = "item1",
        IsLastItem = false
    },
    new Item
    {
        Id = 2,
        ParentId = 1,
        Content = "item2",
        IsLastItem = false
    },
    new Item
    {
        Id = 3,
        ParentId = 1,
        Content = "item3",
        IsLastItem = true
    },
    new Item
    {
        Id = 4,
        ParentId = 1,
        Content = "item4",
        IsLastItem = false
    },
    new Item
    {
        Id = 5,
        ParentId = 2,
        Content = "item5",
        IsLastItem = false
    },
    new Item
    {
        Id = 6,
        ParentId = 5,
        Content = "item6",
        IsLastItem = false
    },
    new Item
    {
        Id = 7,
        ParentId = 5,
        Content = "item7",
        IsLastItem = false
    },
    new Item
    {
        Id = 8,
        ParentId = 6,
        Content = "item8",
        IsLastItem = true
    },
    new Item
    {
        Id = 9,
        ParentId = 8,
        Content = "item9",
        IsLastItem = true
    }
};

4 个答案:

答案 0 :(得分:5)

这样的平面列表对于这些类型的操作来说不是最佳的 - 如果你能够以某种树形结构返回列表(可能使用FOR XML或者JSON从SQL返回它可能会很好) #39;重新开始2016)开始时,您可以更轻松地穿越树木。

另请注意,您的样本数据不是设置IsLastItem ...

按原样,你必须至少迭代两次,如下所示:

items.RemoveAll(x => x.IsLastItem == false && 
    items.Any(y => y.ParentId == x.Id) == false);

您要说删除IsLastItem为假的所有项目,以及其中至少有一项父项ID为该项ID的项目。

答案 1 :(得分:2)

您忘了在模拟数据中设置<nav class="navbar navbar-default navbar-static-top" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" (click)="isMenuCollapsed = !isMenuCollapsed" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button type="button" class="navbar-brand" data-toggle="collapse" (click)="isBrandingCollapsed = !isBrandingCollapsed"> <i *ngIf="isBrandingCollapsed" class="fa fa-chevron-circle-down"></i> <i *ngIf="!isBrandingCollapsed" class="fa fa-chevron-circle-up"></i> </button> </div> <div class="collapse navbar-collapse" (collapsed)="collapsed($event)" (expanded)="expanded($event)" [collapse]="isMenuCollapsed"> <ul class="nav navbar-nav"> <li *ngIf="userHasPermission()" style="display:inline-block;" routerLink="path1/{{shortName}}" routerLinkActive="active" (click)="isMenuCollapsed = true" role="button" dropdown> <i class="fa fa-home fa-lg"></i> {{shortName}} </li><a style="display:inline-block;" dropdownToggle> <b class="caret"></b> </a> <ul dropdownMenu class="list-group" role="menu" aria-labelledby="customer-selection"> <!-- TODO: Figure out why routerLink will not work here and fix it. A full page reload is necessary --> <li routerLink="/admin/new" class="btn btn-default" role="button"><i class="glyphicon glyphicon-plus"></i> {{'add'|translate}}</a> <li *ngFor="let r of recordList" class="list-group-item"> <li class="list-group-item" (click)="selectRecord(r.shortName)">{{r.shortName}}</li> </ul> </li> <li *ngIf="!userHasPermission()" routerLink="path1/{{shortName}}" routerLinkActive="active" (click)="isMenuCollapsed = true" role="button"> <a i18n="Customer menu label"><i class="fa fa-home fa-lg"></i> {{shortName}}</a></li> <li routerLink="path2" routerLinkActive="active" (click)="isMenuCollapsed = true" role="button"> <a i18n="Users menu label"><i class="fa fa-users fa-lg"></i> {{ "path2"|translate }}</a></li> <li routerLink="path3" routerLinkActive="active" (click)="isMenuCollapsed = true" role="button"> <a i18n="Questions menu label"><i class="fa fa-book fa-lg"></i> {{ "path3"|translate }}</a></li> </ul> </div> </div> </nav>,仅供参考。您应该可以使用IsLastItem完成此操作。

RemoveAll

答案 2 :(得分:1)

找到ParentIds。将每个项目与ParentId集合列表进行比较,然后检查IsLastitem。

var parents = items.Select(x => x.ParentId);
items.RemoveAll(x => !parents.Contains(x.Id) && !x.IsLastItem);

答案 3 :(得分:0)

我建议您使用树状结构,并使IsLastItem成为计算的属性:

public class Item
{
    public int Id { get; set; }
    public string Content { get; set; }
    public List<Item> SubItems { get; set; }
    public bool IsLastItem { get { return SubItems.Count == 0; } }
}

由于存储在数据库中的项目将具有平面结构,因此您必须编写一个函数来从数据库创建树(并在必要时将树写入数据库),但是一旦这样做&# 39;完成后,树将更容易操纵。

然后您编写一个递归函数来删除所有最后的节点,如下所示:

List<Item> RemoveNodes(List<Item> tree)
{
    var ret = tree.Where(item => !item.IsLastItem);
    foreach (Item item in ret)
    {
        item.SubItems = RemoveNodes(item.SubItems);
    }
    return ret;
}

这可能不是最好的方法,但你明白了。