Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ筛选保留父级的树列表_C#_Linq - Fatal编程技术网

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();