11

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

I have created the following object model:

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; }
}

Now, I have a list of these organisations and using LINQ, I would like to sort/order the output as follows:

1) Organisations: Ordered by Code and Name

2) Departments: Ordered by Code and Name

3) Employees: Ordered by Code and Name

Below is some test data that I have populated:

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
            };

Here I am adding the data to a dictionary:

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

doing it this way the sorting only happens at the Organisation level and not on the department or the employee level.

My question is, how can I achieve sorting on all 3 levels within the object hierarchy while populating the dictionary above?

Cheers

4
  • 4
    You sort when you query your dictionary, not when you populate it. Commented Sep 17, 2013 at 15:18
  • 2
    If it must happen in this method, then you need to recreate each object and sort the elements while doing this. For example: .OrderBy(x => x.Code).ThenBy(x => x.Name).Select(o => new Organisation() { //populate with data from o, using OrderBy when needed });. However you should probably reconsider your design. Commented Sep 17, 2013 at 15:18
  • @ChrisHardie can't do that. The client needs a sorted dictionary. Commented Sep 17, 2013 at 15:36
  • @BartoszKP I will try your suggestion. Commented Sep 17, 2013 at 15:37

5 Answers 5

14

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

This is the best answer, in my opinion. There is a typo -- Departmets should be Departments and each of the "...ThenBy(...) needs to end with a .ToList();
Thanks for pointing out the typo. As for the .ToList() I don't think it's really necessary. I'll check and let you know.
6

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

1 Comment

Your answer makes sense and I am working on your suggested solution but will get back to you shortly. Cheers
3

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

3 Comments

why use comparer when you have all that functionality implemented within linq ? . Linq's orderby does the job pretty well.
Because 'orderby' does not order 'in place', it generates a new IEnumerable and I need to assign it. 'Sort' method, on the contrary, does the job 'in place'.
2

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

2 Comments

thanks for your suggestion but if i am using linq orderby i shouldnt have the need to implement an IComparer.
@HaroonEmmanuel, if the list is always required to be sorted then it makes sense to sort it only once, rather than sort it with linq every time it's used.
-1
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()
                }
            }

1 Comment

Please provide more information in your answer. Why does this code work better/different than the accepted answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.