You are on page 1of 6

Sorting Arrays and Collections

The key to sorting a list of objects is the ability to compare any two of those objects. No matter the sorting algorithm you choose, to sort a list of objects you must be able to compare a pair of those objects and then be able to decide how to proceed based on the result. The first choice for comparing objects in the .NET Framework is the IComparable interface. The IComparable interface and its generic counterpart define a single CompareTo method. This method compares the current instance to another instance of the same type and returns an Int32 value indicating their relative order. A result less than zero indicates that the current instance comes before the other value, while a result greater than zero indicates that the other value comes first. A zero result indicates that the two values are equivalent. All the primitive .NET data types, including String, implement the IComparable interface, allowing arrays and collections of such values to be sorted automatically, e.g. C#
List<int> numbers = new List<int>(); numbers.Add(7); numbers.Add(2); numbers.Add(5); numbers.Add(3); Console.WriteLine("Before sorting:"); foreach (int number in numbers) { Console.WriteLine(number); } numbers.Sort(); Console.WriteLine("After sorting:"); foreach (int number in numbers) { Console.WriteLine(number); }

VB
Dim numbers As New List(Of Integer) numbers.Add(7) numbers.Add(2) numbers.Add(5) numbers.Add(3)

Console.WriteLine("Before sorting:") For Each number As Integer In numbers Console.WriteLine(number) Next numbers.Sort() Console.WriteLine("After sorting:") For Each number As Integer In numbers Console.WriteLine(number) Next

Sorting arrays is basically the same except that the Array.Sort method is a static/Shared method: C#
int[] numbers = { 7, 2, 5, 3 }; Console.WriteLine("Before sorting:"); foreach (int number in numbers) { Console.WriteLine(number); } Array.Sort(numbers); Console.WriteLine("After sorting:"); foreach (int number in numbers) { Console.WriteLine(number); }

VB
Dim numbers As Integer() = {7, 2, 5, 3} Console.WriteLine("Before sorting:") For Each number As Integer In numbers Console.WriteLine(number) Next Array.Sort(numbers) Console.WriteLine("After sorting:") For Each number As Integer In numbers Console.WriteLine(number) Next

The same principle holds for String, DateTime and any other type that implements the IComparable interface. As such, we can define our own types that implement IComparable and then they will be able to be automatically sorted too. For instance, lets say that we have a Person class and we want them to be inherently sortable by LastName and FirstName. Such a class could look like this: C#
public class Person : IComparable, IComparable<Person> { private string _lastName; private string _firstName; public string LastName { get { return this._lastName; } set { this._lastName = value; } } public string FirstName { get { return this._firstName; } set { this._firstName = value; } } public Person(string firstName, string lastName) { this._firstName = firstName; this._lastName = lastName; } public int CompareTo(object obj) { return this.CompareTo((Person)obj); } public int CompareTo(Person other) { // Compare by LastName by default. int result = this.LastName.CompareTo(other.LastName); // If LastNames are the same...

if (result == 0) { // ...compare by FirstName. result = this.FirstName.CompareTo(this.FirstName); } return result; } }

VB
Public Class Person Implements IComparable, IComparable(Of Person) Private _lastName As String Private _firstName As String Public Property FirstName() As String Get Return Me._firstName End Get Set(ByVal value As String) Me._firstName = value End Set End Property Public Property LastName() As String Get Return Me._lastName End Get Set(ByVal value As String) Me._lastName = value End Set End Property Public Sub New(ByVal firstName As String, _ ByVal lastName As String) Me._firstName = firstName Me._lastName = lastName End Sub Public Function CompareTo(ByVal obj As Object) As Integer _ Implements IComparable.CompareTo Return Me.CompareTo(DirectCast(obj, Person)) End Function Public Function CompareTo(ByVal other As Person) As Integer _ Implements IComparable(Of Person).CompareTo 'Compare by LastName by default. Dim result As Integer = Me.LastName.CompareTo(other.LastName) 'If LastNames are the same... If result = 0 Then '...compare by FirstName. result = Me.FirstName.CompareTo(other.FirstName)

End If Return result End Function End Class

Note that the Person class implements both the standard and generic forms of the IComparable interface, which is a good convention to follow. The Person.CompareTo method makes use of the String.CompareTo method. Using the CompareTo methods of primitive types in your own CompareTo methods is also a good convention to follow, where its feasible. As you can see, two Person objects will first be compared by their LastName properties and then, if those are equivalent, they will be compared by their FirstName properties. Note that I say equivalent rather than equal. We might reimplement our CompareTo method to ignore case, in which case strings that are not equal may still be equivalent. We can now sort an array or collection of Person objects automatically like so: C#
List<Person> people = new List<Person>(); people.Add(new people.Add(new people.Add(new people.Add(new Person("Mary", "Smith")); Person("John", "Williams")); Person("John", "Smith")); Person("Andrew", "Baxter"));

Console.WriteLine("Before sorting:"); foreach (Person person in people) { Console.WriteLine("{0}, {1}", person.LastName, person.FirstName); } people.Sort(); Console.WriteLine("After sorting:"); foreach (Person person in people) { Console.WriteLine("{0}, {1}", person.LastName, person.FirstName); }

VB
Dim people As New List(Of Person)

people.Add(New people.Add(New people.Add(New people.Add(New

Person("Mary", "Smith")) Person("John", "Williams")) Person("John", "Smith")) Person("Andrew", "Baxter"))

Console.WriteLine("Before sorting:") For Each person As Person In people Console.WriteLine("{0}, {1}", _ person.LastName, _ person.FirstName) Next people.Sort() Console.WriteLine("After sorting:") For Each person As Person In people Console.WriteLine("{0}, {1}", _ person.LastName, _ person.FirstName) Next