2017-02-09 20 views
1

删除特定的节点我有下面的类C#如何从列表

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 
    } 
}; 
+0

你想通过ID或所有节点没有孩子?如果你想删除没有孩子的所有节点,为什么你不要删除节点9呢? – osanger

+2

'var enumerable = items.Where(s =>!s.IsLastItem && items.All(t => t.ParentId!= s.Id))。ToList();'??? – Aybe

+0

@MichałZych:用​​户可以创建一个模型,其item4不是最后一项,但我必须清除这些节点。 –

回答

5

像这样的简单列表是不是最佳的这些类型的操作 - 这可能是很好,如果你可以,如果你得到的名单早在某种树结构的(可能使用FOR XML或从SQL返回它的JSON '在2016年)开始,在那里你可以更容易地穿越树。

还要注意的是,由于是,您的样本数据不设置IsLastItem ...

由于是,你必须重复至少两次,这样的事情:

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

你”重新说删除IsLastItem为false并且至少没有一个父项ID为该项目标识的项目的所有项目。

+0

他的答案删除了item9,因为在你的模拟代码块中,你为Item9设置了IsLastItem为false。他的解决方案工作得很好。 – LaggKing

2

你忘了IsLastItem在嘲弄了数据,仅供参考。您应该可以通过RemoveAll完成此操作。

public static void Main() 
{ 
    var items = init(); 
    items.RemoveAll(x => !items.Any(y => y.ParentId == x.Id) == true && x.IsLastItem == false);   

} 

public static List<Item> init() 
{   
    return new List<Item> 
    { 
     new Item 
     { 
      Id = 1, 
      ParentId = 0, 
      Content = "item1" 
     }, 
      new Item 
     { 
      Id = 2, 
      ParentId = 1, 
      Content = "item2" 
     }, 
      new Item 
     { 
      Id = 3, 
      ParentId = 1, 
      Content = "item3", 
      IsLastItem = true 
     }, 
      new Item 
     { 
      Id = 4, 
      ParentId = 1, 
      Content = "item4" 
     }, 
      new Item 
     { 
      Id = 5, 
      ParentId = 2, 
      Content = "item5" 
     }, 
      new Item 
     { 
      Id = 6, 
      ParentId = 5, 
      Content = "item6" 
     }, 
      new Item 
     { 
      Id = 7, 
      ParentId = 5, 
      Content = "item7" 
     }, 
      new Item 
     { 
      Id = 8, 
      ParentId = 6, 
      Content = "item8" 
     }, 
      new Item 
     { 
      Id = 9, 
      ParentId = 8, 
      Content = "item9", 
      IsLastItem = true 
     } 
    };  
} 
+0

抱歉,我忘了将它添加到模型中。我只是编辑问题:) –

1

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

var parents = items.Select(x => x.ParentId); 
items.RemoveAll(x => !parents.Contains(x.Id) && !x.IsLastItem); 
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; } } 
} 

由于存储在数据库中的项目将有一个扁平的结构,你会必须编写一个函数来从数据库创建树(并在必要时将树写出到数据库),但一旦完成,该树将更易于操作。

你会再编写一个递归函数删除所有首尾节点,这样的事情:

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

这可能不完全做到这一点的最好办法,但你的想法。