2017-02-09 16 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

Плоский список, как это не является оптимальным для этих видов операций - это может быть хорошо, если вы могли бы получить список назад в каком-то структуру дерева (возможно, вернуть его из SQL с помощью FOR XML или JSON, если вы на начало 2016 года), где вам будет легче перемещаться по дереву.

отметить также, что, как ваши данные выборки не устанавливая IsLastItem ...

Как есть, вы должны повторять по крайней мере в два раза, что-то вроде этого:

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

You» re говоря, чтобы удалить все элементы, где IsLastItem является ложным и где нет хотя бы одного элемента, родительским идентификатором которого является идентификатор этого элемента.

+0

Он ответил, удалил item9, потому что в вашем симулированном кодовом блоке вы устанавливаете IsLastItem в false для item9. Он работает очень хорошо. – LaggKing

2

Вы забыли установить IsLastItem в ваших издевался вверх данных, FYI. Вы должны сделать это с помощью 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

Найти родительские элементы. Сравните каждый элемент со списком коллекции 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; 
} 

Это не может быть точно лучший способ сделать это, но вы получите идею.