Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 740
Mare Infinitus Avatar asked May 13 '13 08:05

Mare Infinitus


People also ask

Can you sort enum?

If you just create a list of the enum values (instead of strings) via parsing, then sort that list using Collections. sort , it should sort the way you want. If you need a list of strings again, you can just convert back by calling name() on each element.

Can we compare two enums?

There are two ways for making comparison of enum members :equals method uses == operator internally to check if two enum are equal. This means, You can compare Enum using both == and equals method.

Can you use == to compare enums in Java?

By the way unlike comparing String in Java, you can use both == and equals() method to compare Enum, they will produce same result because equals() method of Java. lang. Enum internally uses == to compare enum in Java.


3 Answers

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.

like image 176
Jon Avatar answered Oct 13 '22 14:10

Jon


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
like image 28
Eren Ersönmez Avatar answered Oct 13 '22 14:10

Eren Ersönmez


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! :-)

like image 2
HaGever Avatar answered Oct 13 '22 13:10

HaGever