Mare Infinitus
Mare Infinitus

Reputation: 8182

Comparing Enum values for sorting

In a project I have an external enum (generated from a service reference). So I cannot change the enum values.

How can I compare those enum values to each other in an effective way?

Here an example for an enum

public enum Values
{
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H
}

And the sortorder I want them is not the same (something like F, H, A, C, B, ...)

Right now I have a extension method with some comparisons. (having another enum with the order I want)

public static int CompareTo(this Values x, Values y)
    {
        var orderedX = GetOrderedValues(x);
        var orderedY = GetOrderedValues(y);

        return orderedX.CompareTo(orderedY);
    }


internal enum ValuesOrdered
{
    F = 0,
    H = 1,
    C = 2,
    D = 3,
    B = 4,
    A = 5,
    E = 6,
    G = 7
}

internal static ValuesOrdered GetOrderedValues(this Values x)
{
    switch (x)
    {
        case Values.A:
        {
           return ValuesOrdered.A;
        }

        // and so on...
    }
}

Can this be achieved more effective?

Upvotes: 7

Views: 7574

Answers (3)

HaGever
HaGever

Reputation: 91

instead to enum ValuesOrdered use static readonly SortedList (you cannot use constant for SortedList) like this:

private static readonly SortedList<Values, int> ordered = new SortedList<Values, int> 
    {
        {Values.F,0},
        {Values.H,1},
        {Values.C,2},
        {Values.D,3},
        {Values.B,4},
        {Values.A,5},
        {Values.E,6},
        {Values.G,7},
    };

And method "CompareTo" will be like this:

public static int CompareTo(this Values x, Values y)
    {
        return Comparer<int>.Default.Compare(ordered[x], ordered[y]);
    }

Enjoy! :-)

Upvotes: 2

Eren Ers&#246;nmez
Eren Ers&#246;nmez

Reputation: 39085

If all you want to do is CompareTo, then I think you could simplify this a bit by using a dictionary:

static Dictionary<Values, int> order = new Dictionary<Values, int>
{
    {Values.A, 3},
    {Values.B, 5},
    {Values.C, 4},
    {Values.D, 6},
    {Values.E, 8},
    {Values.F, 1},
    {Values.G, 7},
    {Values.H, 2}
};

public static int CompareTo(this Values x, Values y)
{
    return order[x].CompareTo(order[y]);
}

However, I'm not sure why want to implement an extension method named CompareTo, but I hope you don't expect it to override the Enum.CompareTo. For example,

var values = Enum.GetValues(typeof(Values)).Cast<Values>().ToArray();
Array.Sort(values); 
Console.WriteLine(string.Join(" ", values)); 
//OUTPUT: A B C D E F G H

Upvotes: 4

Jon
Jon

Reputation: 437386

I believe the simplest would be to implement your comparison function in this manner:

public static int CompareTo(this Values x, Values y)
{
    var sortOrder = new[] {
        Values.F,
        Values.H,
        Values.C,
        Values.D,
        Values.B,
        Values.A,
        Values.E,
        Values.G
    };

    return Array.IndexOf(sortOrder, x) - Array.IndexOf(sortOrder, y);
}

Of course you would want to move the initialization of sortOrder outside the function so that it only runs once.

Regarding the choice of array as the data structure that encodes the desired ordering: not only is it the simplest, but for such a small number of items linear search is likely also fastest.

Upvotes: 5

Related Questions