Problem with custom IComparer for List (sort) - c#

mark smith picture mark smith · Jul 4, 2009 · Viewed 8.9k times · Source

can anyone help, i have problem doing a sort, I thought i had it sorted but appears not to be working.

I have a List which stores the following values

8,6,10,11,7

I also have another List (accessories in my class and it has a propert called accessoryId current the classes are in the order of id which is currenty 6,7,8,10,11)

Hence i need to sort them from 6,7,8,10,11 to the order used from the simple list which is 8,6,10,11,7

I have my icomparable (see below) and i am calling like this - it does enter but something is wrong BECAUSE the list still has all my classes but is still in the order of 6,7,8,10,11

   // accesories is the IList<Accessories> (hence why i am use ToList)
   // and sortOrder is the simple int list list<int>
   accesories.ToList().Sort(new ItemTpComparer(sortOrder));  

class ItemTpComparer : IComparer<Accessories>
{
    private IList<int> otherList;

    public ItemTpComparer(IList<int> otherList)
    {
        this.otherList = otherList;
    }

    #region IComparer<Accessories> Members

    public int Compare(Accessories x, Accessories y)
    {

        if (otherList.IndexOf(x.AccessoryId) > otherList.IndexOf(y.AccessoryId))
            return 1;

        else if (otherList.IndexOf(x.AccessoryId) < otherList.IndexOf(y.AccessoryId))
            return -1;
        else
            return 0;

        // tried below also didn't work
        //return otherList.IndexOf(x.AccessoryId) - otherList.IndexOf(y.AccessoryId);

Answer

mmx picture mmx · Jul 4, 2009

The comparer is correct (even the commented single line version). The problem is ToList() creates a new List containing a copy of elements in the IEnumerable<T> object so basically, you are creating a new list, sorting it and throwing it away.

var sortedList = accesories.ToList();
sortedList.Sort(new ItemTpComparer(sortOrder)); 

for which I'd suggest replacing with:

var sortedList = accessories.OrderBy(sortOrder.IndexOf).ToList();

this way, no comparer implementation would be necessary. You could also sort in the descending order easily:

var sortedList = accessories.OrderByDescending(sortOrder.IndexOf).ToList();

If the object is really List<Accessories>, you could also sort it in place:

((List<Accessories>)accessories).Sort(new ItemTpComparer(sortOrder));