Sort a list and all its nested objects using LINQ

前端 未结 5 2052
情书的邮戳
情书的邮戳 2021-01-04 23:49

There is an organisation with several departments and each department has a few employees.

I have created the following object model:

public class O         


        
相关标签:
5条回答
  • 2021-01-05 00:03

    You need to do all three levels of sorting inside the objects that you return, like this (I'll show only the "Retail", the "Institutional" needs to be sorted in the same way):

    {
    "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()
    }
    

    Since you need to select this multiple times, you may want to wrap this code in a method, and use it from several spots, like this:

    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()
                }
            };
    
    0 讨论(0)
  • 2021-01-05 00:06
    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()
                    }
                }
    
    0 讨论(0)
  • 2021-01-05 00:15

    If Employees ever need to be sorted by code and name then you can make that property a SortedList<>.

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

    Prior to .NET 4 you could use KeyValuePair instead of Tuple.

    When creating Employees object you'd need to provide IComparer object for sorted list's key.

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

    where EmployeeKeyComparer could be defined as

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-05 00:19

    I know this is an old question, but there's a simpler way of achieving the same result:

    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); 
    
    0 讨论(0)
  • 2021-01-05 00:21

    You can sort before :

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

    And then use the list already sorted

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

    NB : the sort is not in place, you can achieve this using a comparer

            organisations.ToList().ForEach(o => o.Departments.Sort(CreateCustomComparison));
            organisations.SelectMany(o => o.Departments).ToList().ForEach(d => d.Employees.Sort(CreateCustomComparison));
    
    0 讨论(0)
提交回复
热议问题