Search

Nov 24, 2008

How to sort Hashtable

I was having one requirement for sorting Hashtable. In general you cannot choose the sort order of the items added to the Hashtable. To sort Hashtable best practice is to use SortedList. You can either replace Hashtable with SortedList or you convert Hashtable into SortedList and provided your sort expression. Let's see with example. I have one class name ContactActivity which has contact and activity associated with it. I override ToString method to see the the value of added object.

class ContactActivity
{
public long ActivityId { get; set; }
public long ContactId { get; set; }

public override string ToString()
{
return string.Format("Contact Id : {0} => Activity Id : {1}", ContactId, ActivityId);
}
}

Now we will going to create Hashtable and add few objects of type ContactActivity

Hashtable hs = new Hashtable();

hs.Add("3", new ContactActivity() { ContactId = 3, ActivityId = 1 });
hs.Add("4", new ContactActivity() { ContactId = 4, ActivityId = 4 });
hs.Add("6", new ContactActivity() { ContactId = 6, ActivityId = 5 });
hs.Add("1", new ContactActivity() { ContactId = 1, ActivityId = 1 });

One of the constructor of SortedList; except IDictionary and IComparer; Which initializes a new instance of the SortedList class that contains elements copied from the specified dictionary, has the same initial capacity as the number of elements copied, and is sorted according to the specified IComparer interface. We will use that constructor to build SortedList from Hashtable, and also will provide the logic of sorting key by implementing IComparer interface.

Here is the class which implements IComparer interface

public class MySort : IComparer
{
bool IsAscendingOrder = true;
#region IComparer Members

public int Compare(object x, object y)
{
if (IsAscendingOrder)
return (int.Parse(x.ToString()) - int.Parse(y.ToString()));
else
return (int.Parse(y.ToString()) - int.Parse(x.ToString()));
}
public MySort(bool blnIsAscendingOrder)
{
IsAscendingOrder = blnIsAscendingOrder;
}

#endregion
}

I added one variable to set the order of key also added constructor which used to set sort order. As in my case key will be integer so I use int.Parse else you can use simply string comparison. Lets create one common method to prints the Hashtable or SortedList, as both implements IDictionary interface we can use that to create common method.

private static void Show(IDictionary id)
{
foreach (string strKey in id.Keys)
{
Console.WriteLine(id[strKey].ToString());
}
}

So lets put all together.

Hashtable hs = new Hashtable();

hs.Add("3", new ContactActivity() { ContactId = 3, ActivityId = 1 });
hs.Add("4", new ContactActivity() { ContactId = 4, ActivityId = 4 });
hs.Add("6", new ContactActivity() { ContactId = 6, ActivityId = 5 });
hs.Add("1", new ContactActivity() { ContactId = 1, ActivityId = 1 });

Console.WriteLine("Hashtable values");
Show(hs);
Console.WriteLine("Ascending Order");
SortedList sl = new SortedList(hs, new MySort(true));
Show(sl);
Console.WriteLine("Descending Order");
Show(sl);
sl = new SortedList(hs, new MySort(false));

Let's see the output.

1 comment:

Anonymous said...

another solution is to use linq:

Dim aEntries = From aEntry In myHashtable Order By aEntry.Key Ascending Select aEntry