Sort a list of objects by multiple fields in C#
This post will discuss how to sort a list of objects against the multiple fields in C#.
1. Using LINQ
To create a sorted copy of the list, we can use LINQ’s OrderBy() method. To compare objects against subsequent fields, call the ThenBy() method (or ThenByDescending).
For example, the following code sorts the employee’s list first by the name field and then by the age field, i.e., for employees having the same name, the employee’s age determines the ordering.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using System; using System.Linq; using System.Collections.Generic; public class Person { public string name; public int age; public Person(string name, int age) { this.name = name; this.age = age; } public override string ToString() { return "[" + name + "," + age + "]"; } } public class Example { public static void Main() { Person tom27 = new Person("Tom", 27); Person roger21 = new Person("Roger", 21); Person fred24 = new Person("Fred", 24); Person fred30 = new Person("Fred", 30); List<Person> people = new List<Person>() { tom27, roger21, fred24, fred30 }; List<Person> sorted = people.OrderBy(x => x.name) .ThenBy(x => x.age) .ToList(); Console.WriteLine(String.Join(Environment.NewLine, sorted)); } } /* Output: [Fred,24] [Fred,30] [Roger,21] [Tom,27] */ |
2. Using List<T>.Sort method (System.Collections.Generic)
The above LINQ solution creates a new sorted copy of the list. The suggested approach is to use List’s Sort() method to sort the list in-place. The sorting can be done using a Comparison<T> delegate or an IComparer<T>/IComparable<T> implementation.
1. We can use a comparison delegate to provide order on objects that don’t have a natural ordering. If passed to a sort method, it allows precise control over the sort order of elements. A comparison delegate can be implemented using lambda expressions. To compare the List of Employee objects first by name and then by age, we can do:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
using System; using System.Linq; using System.Collections.Generic; public class Person { public string name; public int age; public Person(string name, int age) { this.name = name; this.age = age; } public override string ToString() { return "[" + name + "," + age + "]"; } } public class Example { public static void Main() { Person tom27 = new Person("Tom", 27); Person roger21 = new Person("Roger", 21); Person fred24 = new Person("Fred", 24); Person fred30 = new Person("Fred", 30); List<Person> people = new List<Person>() { tom27, roger21, fred24, fred30 }; people.Sort((x, y) => { int ret = String.Compare(x.name, y.name); return ret != 0 ? ret : x.age.CompareTo(y.age); }); Console.WriteLine(String.Join(Environment.NewLine, people)); } } /* Output: [Fred,24] [Fred,30] [Roger,21] [Tom,27] */ |
2. Another approach is to provide the custom IComparer<T> implementation for sorting a list using the Sort() method. The idea is to implement the IComparer<T> interface in a separate class, override its Compare() method, and pass that class’s instance to the Sort() method. This is the preferred approach to lambda expressions when you have several fields to compare.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using System; using System.Collections.Generic; public class PersonComparer: IComparer<Person> { public int Compare(Person x, Person y) { if (object.ReferenceEquals(x, y)) { return 0; } if (x == null) { return -1; } if (y == null) { return 1; } int ret = String.Compare(x.name, y.name); return ret != 0 ? ret : x.age.CompareTo(y.age); } } public class Person { public string name; public int age; public Person(string name, int age) { this.name = name; this.age = age; } public override string ToString() { return "[" + name + "," + age + "]"; } } public class Example { public static void Main() { Person tom27 = new Person("Tom", 27); Person roger21 = new Person("Roger", 21); Person fred24 = new Person("Fred", 24); Person fred30 = new Person("Fred", 30); List<Person> people = new List<Person>() { tom27, roger21, fred24, fred30 }; people.Sort(new PersonComparer()); Console.WriteLine(String.Join(Environment.NewLine, people)); } } /* Output: [Fred,24] [Fred,30] [Roger,21] [Tom,27] */ |
3. The IComparable<T> interface imposes a natural ordering on the objects of each class that implements it. In the following code, the Employee class implements the IComparable<T> interface and override its CompareTo() method. The List of Employee objects is then sorted using the no-arg Sort() method.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using System; using System.Collections.Generic; public class Person: IComparable<Person> { public string name; public int age; public Person(string name, int age) { this.name = name; this.age = age; } public int CompareTo(Person emp) { if (emp == null) { return 1; } int ret = String.Compare(this.name, emp.name); return ret != 0 ? ret : this.age.CompareTo(emp.age); } public override string ToString() { return "[" + name + "," + age + "]"; } } public class Example { public static void Main() { Person tom27 = new Person("Tom", 27); Person roger21 = new Person("Roger", 21); Person fred24 = new Person("Fred", 24); Person fred30 = new Person("Fred", 30); List<Person> people = new List<Person>() { tom27, roger21, fred24, fred30 }; people.Sort(); Console.WriteLine(String.Join(Environment.NewLine, people)); } } /* Output: [Fred,24] [Fred,30] [Roger,21] [Tom,27] */ |
That’s all about sorting a list of objects by multiple fields in C#.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)