C# 使用LINQ筛选保留父级的树列表
我有一个模型类,看起来像这样:C# 使用LINQ筛选保留父级的树列表,c#,linq,C#,Linq,我有一个模型类,看起来像这样: public class Employee { public int Id {get;set;} public int ParentId {get;set;} public string Name{get;set;} public string Designation {get;set;} public List<Employee> Reportees {get;set;} } 我用它模拟了一个带有数据的演示
public class Employee
{
public int Id {get;set;}
public int ParentId {get;set;}
public string Name{get;set;}
public string Designation {get;set;}
public List<Employee> Reportees {get;set;}
}
我用它模拟了一个带有数据的演示树列表:
var employees = new List<Employee>
{
new Employee
{
Id = 1,
ParentId = 0,
Name = "A",
Designation = "CEO",
Reportees = new List<Employee>
{
new Employee { Id = 2, ParentId = 1,Name = "B",Designation = "Manager",Reportees = new List<Employee>
{
new Employee { Id = 4, ParentId = 2, Name = "D", Designation = "Lead", Reportees = new List<Employee>
{
new Employee { Id = 6, ParentId = 4, Name = "F", Designation = "Developer", Reportees = new List<Employee>() },
new Employee { Id = 7, ParentId = 4, Name = "G", Designation = "Developer", Reportees = new List<Employee>() }
}},
new Employee { Id = 3, ParentId = 1,Name = "C",Designation = "Manager",Reportees = new List<Employee>
{
new Employee { Id = 5, ParentId = 3, Name = "E", Designation = "Lead", Reportees = new List<Employee>
{
new Employee { Id = 8, ParentId = 5, Name = "H", Designation = "Developer", Reportees = new List<Employee>() }
}}
}}
}}
}
}
};
如果子对象满足过滤条件,我需要过滤上面的列表以显示父对象。这里还有一个问题是,如果父项满足条件,而子项不满足条件,则忽略它们
是否有可用的扩展,或者我可以使用LINQ来实现这一点
为了更清楚地说明这是在筛选搜索条件为Ids 6和Ids 7的情况下预期的筛选列表:
如果要筛选的Id为6:
如果要筛选的Id为2:
我有两个解决方案: 1创建一个函数以从其ID访问employee对象 2创建childsID属性,如:
new Employee{Id = 1,ParentId = 0, childsID=new list<int>(){2,4,6,7}, ...}
在这两种方法之后,您可以使用linq轻松完成这项工作。我有两种解决方案供您选择: 1创建一个函数以从其ID访问employee对象 2创建childsID属性,如:
new Employee{Id = 1,ParentId = 0, childsID=new list<int>(){2,4,6,7}, ...}
在这两种方法之后,您可以使用linq轻松完成这项工作,以下是您需要的方法:
List<Employee> FilterEmployees(List<Employee> source, Func<Employee, bool> predicate) =>
source
.Select(e => new { employee = e, reportees = FilterEmployees(e.Reportees, predicate) })
.Where(x => predicate(x.employee) || x.reportees.Any())
.Select(x => new Employee
{
Id = x.employee.Id,
ParentId = x.employee.ParentId,
Name = x.employee.Name,
Designation = x.employee.Designation,
Reportees = x.reportees,
})
.ToList();
该方法的两条关键线是第一选择和位置
第一个选择跟踪当前员工,并递归调用FilterEmployees以获取匹配的任何报告对象
Where决定我们是否要保留当前员工——标准是该员工是否满足谓词或其任何报告对象
最后,它只是构建新员工返回
对于FilterEmployeesemployees,e=>e.Id==6 | | e.Id==7,我们得到:
对于FilterEmployeesemployees,e=>e.Id==6,我们得到:
对于FilterEmployeesemployees,e=>e.Id==2,我们得到:
以下是您需要的方法:
List<Employee> FilterEmployees(List<Employee> source, Func<Employee, bool> predicate) =>
source
.Select(e => new { employee = e, reportees = FilterEmployees(e.Reportees, predicate) })
.Where(x => predicate(x.employee) || x.reportees.Any())
.Select(x => new Employee
{
Id = x.employee.Id,
ParentId = x.employee.ParentId,
Name = x.employee.Name,
Designation = x.employee.Designation,
Reportees = x.reportees,
})
.ToList();
该方法的两条关键线是第一选择和位置
第一个选择跟踪当前员工,并递归调用FilterEmployees以获取匹配的任何报告对象
Where决定我们是否要保留当前员工——标准是该员工是否满足谓词或其任何报告对象
最后,它只是构建新员工返回
对于FilterEmployeesemployees,e=>e.Id==6 | | e.Id==7,我们得到:
对于FilterEmployeesemployees,e=>e.Id==6,我们得到:
对于FilterEmployeesemployees,e=>e.Id==2,我们得到:
我不相信,有任何扩展。您可以使用递归搜索。并且请分享你已经知道的代码tried@PavelAnikhouski我所做的是展平树列表并过滤结果列表,然后重新构建树。但是不要认为这是最有效的解决方案,尽管我能够得到我所得到的结果数据过滤器释放、共享您当前的解决方案并编译您的代码示例,因为新列表员工是无效的声明,我不相信,有任何扩展。您可以使用递归搜索。并且请分享你已经知道的代码tried@PavelAnikhouski我所做的是展平树列表并过滤结果列表,然后重新构建树。但是不要认为这是最有效的解决方案,尽管我能够得到我所得到的结果数据过滤器。请共享您当前的解决方案,并使您的代码示例得以编译,因为新的列表雇员是无效的声明。请演示如何使用真正的可编译C代码创建childsID属性。还请说明如何使用linq轻松完成此工作。请说明如何使用真正的可编译C代码创建childsID属性。还请展示如何轻松地使用linq完成工作。
List<Employee> FilterEmployees(List<Employee> source, Func<Employee, bool> predicate) =>
source
.Select(e => new { employee = e, reportees = FilterEmployees(e.Reportees, predicate) })
.Where(x => predicate(x.employee) || x.reportees.Any())
.Select(x => new Employee
{
Id = x.employee.Id,
ParentId = x.employee.ParentId,
Name = x.employee.Name,
Designation = x.employee.Designation,
Reportees = x.reportees,
})
.ToList();