使用 LINQ 对列表及其所有嵌套对象进行排序

本文关键字:对象 嵌套 排序 LINQ 列表 使用 | 更新日期: 2023-09-27 18:31:50

有一个组织有几个部门,每个部门都有几名员工。

我创建了以下对象模型:

public class Organisation
{
    public int Code { get; set; }
    public string Type { get; set; }
    public string Name { get; set; }
    public List<Department> Departments { get; set; }
}
public class Department
{
    public int Code { get; set; }
    public string Name { get; set; }
    public List<Employee> Employees { get; set; }
}
public class Employee
{
    public int Code { get; set; }
    public string Name { get; set; }
}

现在,我有一个这些组织的列表,使用 LINQ,我想对输出进行排序/排序,如下所示:

1) 组织:按代码和名称排序

2)部门:按代码和名称排序

3)员工:按代码和姓名排序

以下是我填充的一些测试数据:

var britishTelecomLtd = new Organisation
            {
                Code = 8,
                Name = "British Telecom Ltd",
                Type = "Institutional",
                Departments =  new List<Department>
                    {
                        new Department
                            {
                                Code = 6,
                                Name = "Finance",
                                Employees = new List<Employee>
                                    {
                                        new Employee
                                            {
                                                Code = 5,
                                                Name = "Peter"
                                            },
                                            new Employee
                                            {
                                                Code = 2,
                                                Name = "James"
                                            },
                                            new Employee
                                            {
                                                Code = 6,
                                                Name = "Andrew"
                                            }
                                    }
                            },
                            new Department
                            {
                                Code = 5,
                                Name = "Accounts",
                                Employees = new List<Employee>
                                    {
                                        new Employee
                                            {
                                                Code = 15,
                                                Name = "Jane"
                                            },
                                            new Employee
                                            {
                                                Code = 22,
                                                Name = "John"
                                            },
                                            new Employee
                                            {
                                                Code = 16,
                                                Name = "Mark"
                                            }
                                    }
                            }
                    } 
            };
        var virginMediaLtd = new Organisation
        {
            Code = 5,
            Name = "Virgin Media Ltd",
            Type = "Institutional",
            Departments = new List<Department>
                    {
                        new Department
                            {
                                Code = 6,
                                Name = "Sales",
                                Employees = new List<Employee>
                                    {
                                       new Employee
                                            {
                                                Code = 5,
                                                Name = "Peter"
                                            },
                                            new Employee
                                            {
                                                Code = 2,
                                                Name = "James"
                                            },
                                            new Employee
                                            {
                                                Code = 6,
                                                Name = "Andrew"
                                            }
                                    }
                            },
                            new Department
                            {
                                Code = 5,
                                Name = "Support",
                                Employees = new List<Employee>
                                    {
                                        new Employee
                                            {
                                                Code = 15,
                                                Name = "Jane"
                                            },
                                            new Employee
                                            {
                                                Code = 22,
                                                Name = "John"
                                            },
                                            new Employee
                                            {
                                                Code = 16,
                                                Name = "Mark"
                                            }
                                    }
                            }
                    }
        };
        var pcWorldLtd = new Organisation
        {
            Code = 18,
            Name = "PC World Ltd",
            Type = "Retail",
            Departments = new List<Department>
                    {
                        new Department
                            {
                                Code = 6,
                                Name = "Marketing",
                                Employees = new List<Employee>
                                    {
                                          new Employee
                                            {
                                                Code = 15,
                                                Name = "Jane"
                                            },
                                            new Employee
                                            {
                                                Code = 22,
                                                Name = "John"
                                            },
                                            new Employee
                                            {
                                                Code = 16,
                                                Name = "Mark"
                                            }
                                    }
                            },
                            new Department
                            {
                                Code = 5,
                                Name = "Customer Services",
                                Employees = new List<Employee>
                                    {
                                         new Employee
                                            {
                                                Code = 5,
                                                Name = "Kelly"
                                            },
                                            new Employee
                                            {
                                                Code = 2,
                                                Name = "Jenny"
                                            },
                                            new Employee
                                            {
                                                Code = 6,
                                                Name = "Tricia"
                                            }
                                    }
                            }
                    }
        };
        var blueCatLtd = new Organisation
            {
                Code = 3,
                Name = "Blue Cat Music Ltd",
                Type = "Retail",
                Departments = new List<Department>
                    {
                        new Department
                            {
                                Code = 6,
                                Name = "Sales",
                                Employees = new List<Employee>
                                    {
                                         new Employee
                                            {
                                                Code = 5,
                                                Name = "Peter"
                                            },
                                            new Employee
                                            {
                                                Code = 2,
                                                Name = "James"
                                            },
                                            new Employee
                                            {
                                                Code = 6,
                                                Name = "Andrew"
                                            }
                                    }
                            },
                        new Department
                            {
                                Code = 5,
                                Name = "Warehouse",
                                Employees = new List<Employee>
                                    {
                                        new Employee
                                            {
                                                Code = 5,
                                                Name = "Andy"
                                            },
                                        new Employee
                                            {
                                                Code = 2,
                                                Name = "Robert"
                                            },
                                        new Employee
                                            {
                                                Code = 6,
                                                Name = "Dave"
                                            }
                                    }
                            }
                    }
            };
        var organisations = new List<Organisation>
            {
                britishTelecomLtd,
                virginMediaLtd,
                pcWorldLtd,
                blueCatLtd
            };

在这里,我将数据添加到字典中:

   var legalEntitiesCollectionByType = new Dictionary<string, ICollection<Organisation>>
            {
                {
                    "Institutional", organisations
                        .Where(x => x.Type == "Institutional")
                        .OrderBy(x => x.Code).ThenBy(x => x.Name)
                        .ToList()
                },
                {
                    "Retail", organisations
                        .Where(x => x.Type == "Retail")
                        .OrderBy(x => x.Code).ThenBy(x => x.Name)
                        .ToList()
                }
            };

这样做,排序只发生在组织级别,而不是部门或员工级别。

我的问题是,如何在填充上面的字典时实现对象层次结构中所有 3 个级别的排序?

干杯

使用 LINQ 对列表及其所有嵌套对象进行排序

我知道

这是一个老问题,但有一种更简单的方法可以实现相同的结果:

organisations = organisations.OrderBy(org =>
{
   org.Departments = org.Departments
   .OrderBy(dept =>
   {
     dept.Employees = dept.Employees
                     .OrderBy(employee => employee.Code)
                     .ThenBy(employee=>employee.Name);
     return dept.Code;
   })
   .ThenBy(dept=>dept.Name);
   return org.Code;
})
.ThenBy(org=>org.Name); 

您需要在返回的对象中进行所有三个级别的排序,如下所示(我只显示"Retail""Institutional"需要以相同的方式排序):

{
"Retail", organisations
    .Where(x => x.Type == "Retail")
    .OrderBy(x => x.Code).ThenBy(x => x.Name)
    .Select(x => new Organisation {
        x.Code
    ,   x.Type
    ,   x.Name
    ,   Departments = x.Departmentsd.OrderBy(d => d.Code).ThenBy(d => d.Name)
        .Select(d => new Department {
            d.Code
        ,   d.Name
        ,   Employees = d.Employees.OrderBy(e => e.Code).ThenBy(e => e.Name).ToList()
        })
    }).ToList()
}

由于需要多次选择此选项,因此可能需要将此代码包装在方法中,并从多个位置使用它,如下所示:

private Organisation SortedOrganisation(Organisation x) {
    return new Organisation {
        x.Code
    ,   x.Type
    ,   x.Name
    ,   Departments = x.Departmentsd.OrderBy(d => d.Code).ThenBy(d => d.Name)
        .Select(d => new Department {
            d.Code
        ,   d.Name
        ,   Employees = d.Employees.OrderBy(e => e.Code).ThenBy(e => e.Name).ToList()
        })
    };
}
...
var legalEntitiesCollectionByType = new Dictionary<string, ICollection<Organisation>>
        {
            {
                "Institutional", organisations
                    .Where(x => x.Type == "Institutional")
                    .OrderBy(x => x.Code).ThenBy(x => x.Name)
                    .Select(SortedOrganisation)
                    .ToList()
            },
            {
                "Retail", organisations
                    .Where(x => x.Type == "Retail")
                    .OrderBy(x => x.Code).ThenBy(x => x.Name)
                    .Select(SortedOrganisation)
                    .ToList()
            }
        };

您可以在以下之前排序:

    organisations.ToList().ForEach(o => o.Departments = o.Departments.OrderBy(d => d.Code).ToList());
    organisations.SelectMany(o => o.Departments).ToList().ForEach(d => d.Employees = d.Employees.OrderBy(e => e.Name).ToList());

然后使用已经排序的列表

        var legalEntitiesCollectionByType = new Dictionary<string, ICollection<Organisation>>
        {
            {
                "Institutional", organisations
                    .Where(x => x.Type == "Institutional")
                    .ToList()
            },
            {
                "Retail", organisations
                    .Where(x => x.Type == "Retail")
                    .ToList()
            }
        };

注意:排序不到位,您可以使用comparer来实现此目的

        organisations.ToList().ForEach(o => o.Departments.Sort(CreateCustomComparison));
        organisations.SelectMany(o => o.Departments).ToList().ForEach(d => d.Employees.Sort(CreateCustomComparison));

如果需要按代码和名称对Employees排序,则可以将该属性设置为SortedList<>

public class Department
{
    ...
    public SortedList<Tuple<int, string>, Employee> Employees { get; set; }
}

在 .NET 4 之前,您可以使用 KeyValuePair 而不是 Tuple

创建Employees对象时,您需要为排序列表的键提供IComparer对象。

Employees = new SortedList<Tuple<int, string>, Employee>(new EmployeeKeyComparer());

其中EmployeeKeyComparer可以定义为

public class EmployeeKeyComparer : IComparer<Tuple<int, string>>
{
    public int Compare(Tuple<int, string> x, Tuple<int, string> y)
    {
        if (x.First == y.First)
            return StringComparer.Ordinal.Compare(x.Second, y.Second);
        else
            return x.First.CompareTo(y.First);
    }
}
var legalEntitiesCollectionByType = new Dictionary<string, ICollection<Organisation>>
            {
                {
                    "Institutional", organisations
                        .Where(x => x.Type == "Institutional")
                        .ToList()
                        .Select(o => new Organisation{Code = x.Code,Departaments = x.Departaments.OrderBy(c => c).ToList()  }).ToList()
                }
            }