Sorting List with Custom object by another List using IComparer
Asked Answered
R

3

5

My question is about the IComparer interface, I never worked with it before, so I hope you can help me set up everything right.

I have to use the interface to sort an list of own objects by the exact sequence of another List<int>. I couldn't find anything usefull with that problem on the net, everything I found were linq statements, that I can not use.

Here is the example code:

public class What : IComparer<What>
{
    public int ID { get; set; }
    public string Ever { get; set; }

    public What(int x_ID, string x_Ever)
    {
        ID = x_ID;
        Ever = x_Ever;
    }

    public int Compare(What x, What y)
    {
        return x.ID.CompareTo(y.ID);
    }
}

Some data to work with:

List<What> WhatList = new List<What>()
{
    new What(4, "there"),
    new What(7, "are"), 
    new What(2, "doing"),
    new What(12, "you"),
    new What(78, "Hey"),
    new What(63, "?")
};

And the list with the correct order:

List<int> OrderByList = new List<int>() { 78, 4, 63, 7, 12, 2 };

So now how can I tell IComparer to sort by the OrderByList? I really got no clue how to do that, I know this would be pretty easy with linq, but I don't have the opportunity to use it.

Rhaetic answered 13/12, 2012 at 12:4 Comment(2)
Out of interest, why no LINQ?Domash
Is it safe to assume that all the ID values will exist in your OrderBylist set?Roadway
D
6

There are a few tings wrong with your code as it currently stands. If you look at the docs for IComparer<T> you'll see that the T is what you're saying you are going to compare. In your code this is Test but you go on to code for comparisons of What - this means that your code will not compile. See here - error message is:

'Rextester.What' does not implement interface member 'System.Collections.Generic.IComparer.Compare(Rextester.Test, Rextester.Test)'
(Ignore the "Rextester" bit there!).

With all that said and done, you should implement a WhatComparer:

public class WhatComparer : IComparer<What>
{
    private List<int> orderBy;
    public WhatComparer(List<int> orderBy)
    {
        this.orderBy = orderBy;
    }

    public int Compare(What x, What y)
    {
        return orderBy.IndexOf(x.ID).CompareTo(orderBy.IndexOf(y.ID));
    }
}

And use that for ordering:

 WhatList.Sort(new WhatComparer(OrderByList));

Live example: http://rextester.com/BZKO33641

Domash answered 13/12, 2012 at 12:11 Comment(0)
D
3

You should create another class to do the comparison, and give the desired order to that:

public class OrderComparer : IComparer<What>
{
    private readonly Dictionary<int, int> idIndexes = new Dictionary<int, int>();
    public OrderComparer(List<int> idOrders)
    {
        for(int i = 0; i < idOrders.Length; i++)
        {
            idIndexes[idOrders[i].ID] = i;
        }
    }

    public int Compare(What x, What y)
    {
        return idOrders[x.ID].Compare(idOrders[y.ID]);
    }
}

Then you can do:

WhatList.Sort(new OrderComparer(OrderByList));
Dygert answered 13/12, 2012 at 12:14 Comment(0)
F
2

The simplest way is to use a custom Comparison<T>:

WhatList.Sort((x, y) =>
{
    return OrderByList.IndexOf(x.ID).CompareTo(orderByList.IndexOf(y.ID));
});
Forwardness answered 13/12, 2012 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.