我需要一个C#LINQ查询,我根据它们是否与另一个列表中的属性匹配来删除列表中的对象。另外,这些对象可以包含相同类型的子对象,如果没有匹配,我也需要删除它们。
在我的例子中,我也想删除孩子的孩子。匹配不需要是分层的 - 只是基本匹配。这是我的课程和失败的尝试。任何帮助都会很棒!
public class GsdMegaMenu
{
public int Id { get; set; }
public int PortalId { get; set; }
public int TabId { get; set; }
}
public class MenuItem
{
public int Id { get; set; }
public int PortalId { get; set; }
public int TabId { get; set; }
public List<MenuItem> Children { get; set; }
}
List<GsdMegaMenu> megaMenuItems = GsdMegaMenu.GetAllGsdMegaMenus();
RootNode.Children.RemoveAll(x => !megaMenuItems.Any(y => y.TabId == x.TabId));
答案 0 :(得分:2)
如果你还需要处理孩子的孩子,你必须明确地循环它们。 RemoveAll不是linq方法,它是List
类的方法。您需要在每个子列表上调用它。
RootNode.Children.RemoveAll(x => megaMenuItems.All(y => y.TabId != x.TabId));
foreach (MenuItem node in RootNode.Children)
{
if (node.Children != null)
{
node.Children.RemoveAll(x => megaMenuItems.All(y => y.TabId != x.TabId));
}
}
<强>更新强>
如果你是纯粹的LINQ解决方案,它必须是只读的,即它不能操纵现有的列表,它可以创建新的列表。我不会在你的情况下推荐它。在你的情况下,上面的循环似乎更合适。
RootNode = RootNode.Children.Where(x => megaMenuItems.Select(y => y.TabId).Contains(x.TabId))
.Select(z => new MenuItem
{
Id = z.Id, PortalId = z.PortalId, TabId = z.TabId,
Children = z.Children == null ? null
: z.Children.Where(x => megaMenuItems.Select(y => y.TabId).Contains(x.TabId)).ToList()
})
.ToList();
为了提高效率(在你的情况下并不重要),你也可以将其重写为:
Func<MenuItem, bool> predicate = x => megaMenuItems.Select(y => y.TabId).Contains(x.TabId);
RootNode = RootNode.Children.Where(predicate)
.Select(z => new MenuItem
{
Id = z.Id, PortalId = z.PortalId, TabId = z.TabId,
Children = z.Children == null ? null
: z.Children.Where(predicate).ToList()
})
.ToList();