C# 如何从列表中删除特定节点
C# How to remove specific nodes from list
我有以下class
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 应该从列表中删除。
我从数据库中获取我的模型列表,并在代码块中像这样模拟它
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
}
};
您忘记在模拟数据中设置 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
}
};
}
像这样的平面列表对于这些类型的操作来说并不是最佳选择 - 如果您能以某种树结构恢复列表(可能 return 它来自 SQL 可能会更好使用 FOR XML
或 JSON 如果你在 2016 年)开始,你可以更轻松地遍历树。
另请注意,您的样本数据并未设置 IsLastItem...
照原样,您必须至少迭代两次,如下所示:
items.RemoveAll(x => x.IsLastItem == false &&
items.Any(y => y.ParentId == x.Id) == false);
您是说要删除所有 IsLastItem
为假且没有至少一项的父 ID 是该项 ID 的项目。
找到 ParentIds。将每个项目与 ParentId 集合的列表进行比较并检查 IsLastitem。
var parents = items.Select(x => x.ParentId);
items.RemoveAll(x => !parents.Contains(x.Id) && !x.IsLastItem);
我建议您使用 tree-like 结构,并使 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;
}
这可能不是最好的方法,但您明白了。
我有以下class
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 应该从列表中删除。
我从数据库中获取我的模型列表,并在代码块中像这样模拟它
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
}
};
您忘记在模拟数据中设置 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
}
};
}
像这样的平面列表对于这些类型的操作来说并不是最佳选择 - 如果您能以某种树结构恢复列表(可能 return 它来自 SQL 可能会更好使用 FOR XML
或 JSON 如果你在 2016 年)开始,你可以更轻松地遍历树。
另请注意,您的样本数据并未设置 IsLastItem...
照原样,您必须至少迭代两次,如下所示:
items.RemoveAll(x => x.IsLastItem == false &&
items.Any(y => y.ParentId == x.Id) == false);
您是说要删除所有 IsLastItem
为假且没有至少一项的父 ID 是该项 ID 的项目。
找到 ParentIds。将每个项目与 ParentId 集合的列表进行比较并检查 IsLastitem。
var parents = items.Select(x => x.ParentId);
items.RemoveAll(x => !parents.Contains(x.Id) && !x.IsLastItem);
我建议您使用 tree-like 结构,并使 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;
}
这可能不是最好的方法,但您明白了。