Thursday 7 May 2015

SortedList

A SortedList is a list that has both a key and an index, it also maintains order by the key as things are added, assuming that the key implements IComparable.

to get started in your command line create a Console application with the old school main method

dotnet new console -n pav.sortedListExample  --use-program-main

once you've created your console app, navigate into it with 

cd pav.sortedListExample

after that open it in your ms code with 

code .

Now Let's code up an example


using System.Collections;

namespace pc.SortedListExample
{
    class Program
    {
        static void Main(string[] args)
        {
            SortedList sl = new SortedList();

            sl.Add(3, "Three");
            sl.Add(7, "Seven");
            sl.Add(2, "Two");
            sl.Add(6, 6.0);
            sl.Add(4, 4);
            sl.Add(5, "Five");
            sl.Add(1, "One");

            foreach (DictionaryEntry i in sl)
                Console.WriteLine("{0}: {1}", i.Key, i.Value);

            for (int i = 0; i < sl.Count; i++)
                Console.WriteLine(sl[i]);
        }
    }

}


If you run the above code, you'll notice that the collection is sorted, on the key, this is only possible because int implements the IComparable interface. 

If it didn't then you would get an "Unhandled exception. System.InvalidOperationException: Failed to compare two elements in the array."

In this iteration, rather than using an int, I simply wrap an integer and do not implement the IComparable interface, resulting in an error.


using System.Collections;

namespace pc.SortedListExample
{
    public class MyId //: IComparable
    {
        private static int runningId = 0;
        public int Value { get; }
        public MyId(){ Value = runningId++; }
        public MyId(int value){ Value = value; }

        // public int CompareTo(object? obj)
        // {
 
        //      if(obj as MyId != null)
        //         return this.Value.CompareTo(((MyId)obj).Value);
        //     return 0;
        // }
    }
   
    class Program
    {
        static void Main(string[] args)
        {
            SortedList sl = new SortedList();
           
            sl.Add(new MyId(), "Three");
            sl.Add(new MyId(), "Seven");
            sl.Add(new MyId(), "Two");
            sl.Add(new MyId(), 6.0);
            sl.Add(new MyId(), 4);
            sl.Add(new MyId(), "Five");
            sl.Add(new MyId(), "One");

            foreach (DictionaryEntry de in sl)
                Console.WriteLine("{0}: {1}", ((MyId)de.Key).Value, de.Value);

            for (int i = 0; i < sl.Count; i++)
                Console.WriteLine(sl[new MyId(i)]);
        }
    }

}




To fix this all I simply have to do is implement the IComparable interface on myId class and everything will work again.


using System.Collections;

namespace pc.SortedListExample
{
    public class MyId : IComparable
    {
        private static int runningId = 0;
        public int Value { get; }
        public MyId(){ Value = runningId++; }
        public MyId(int value){ Value = value; }

        public int CompareTo(object? obj)
        {
             if(obj as MyId != null)
                return this.Value.CompareTo(((MyId)obj).Value);
            return 0;
        }
    }
   
    class Program
    {
        static void Main(string[] args)
        {
            SortedList sl = new SortedList();
           
            sl.Add(new MyId(), "Three");
            sl.Add(new MyId(), "Seven");
            sl.Add(new MyId(), "Two");
            sl.Add(new MyId(), 6.0);
            sl.Add(new MyId(), 4);
            sl.Add(new MyId(), "Five");
            sl.Add(new MyId(), "One");

            foreach (DictionaryEntry de in sl)
                Console.WriteLine("{0}: {1}", ((MyId)de.Key).Value, de.Value);

            for (int i = 0; i < sl.Count; i++)
                Console.WriteLine(sl[new MyId(i)]);
        }
    }

}


Notice that we can either iterate using a foreach or display things using the index. Sorted lists work best with one type for your key, if your keys are made of different types then using a hashtable is more effective.