HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Comparer that compares by int than by enum type

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
comparesthanenumtypethatcomparerint

Problem

Below is the implementation of a comparer that compares objects of type Region first by index and then by it's type. The sort order of the type is defined within the comparer.

I know, it's a trivial piece of code, however I am happy about any comments about the realization. :)

public class Region
{
    public RegionType Type { get; set; }
    public int Index { get; set; }
}

public enum RegionType
{
    DeletionBeforeNamedRegion,
    DeletionWithinNamedRegion,
    DeletionAfterNamedRegion,
    InsertionBetweenNamedRegions,
    InsertionWithinNamedRegion,
    NamedRegion,
}

public class RegionComparer : IComparer
{
    private static readonly List sortOrderByType = new List
        {
            RegionType.DeletionBeforeNamedRegion,
            RegionType.NamedRegion,
            RegionType.DeletionWithinNamedRegion,
            RegionType.InsertionWithinNamedRegion,
            RegionType.DeletionAfterNamedRegion,
            RegionType.InsertionBetweenNamedRegions,
        };

    public int Compare(Region x, Region y)
    {
        if (x == null && y == null)
            return 0;
        if (x == null) return -1;
        if (y == null) return 1;

        var result = x.Index.CompareTo(y.Index);
        if (result != 0) return result;

        var xSort = sortOrderByType.IndexOf(x.Type);
        var ySort = sortOrderByType.IndexOf(y.Type);

#if DEBUG
        if (xSort < 0 || ySort < 0)
            throw new NotImplementedException($"Sort order for region type '{(xSort < 0 ? x.Type : y.Type)}' is not defined. Please extend the '{nameof(sortOrderByType)}' list." );
#else
        if (xSort < 0) xSort = int.MaxValue;
        if (ySort < 0) ySort = int.MaxValue;
#endif
        return xSort.CompareTo(ySort);
    }
}

Solution

private static readonly List sortOrderByType = new List
{
    RegionType.DeletionBeforeNamedRegion,
    RegionType.NamedRegion,
    RegionType.DeletionWithinNamedRegion,
    RegionType.InsertionWithinNamedRegion,
    RegionType.DeletionAfterNamedRegion,
    RegionType.InsertionBetweenNamedRegions,
};


Sorting needs to be fast, right? So how about using a dictionary for the oder lookup and not the O(n) List.IndexOf?

private static readonly Dictionary _regionTypeOrder = new RegionType[] 
{
    RegionType.DeletionBeforeNamedRegion,
    RegionType.NamedRegion,
    RegionType.DeletionWithinNamedRegion,
    RegionType.InsertionWithinNamedRegion,
    RegionType.DeletionAfterNamedRegion,
    RegionType.InsertionBetweenNamedRegions,
}
.Select((x, i) => new { Key = x, Order = i })
.ToDictionary(x => x.Key, x => x.Order);


with it, the lines

var xSort = sortOrderByType.IndexOf(x.Type);
var ySort = sortOrderByType.IndexOf(y.Type);


can become

var xSort = _regionTypeOrder[x.Type];
var ySort = _regionTypeOrder[y.Type];


var xSort = sortOrderByType.IndexOf(x.Type);
var ySort = sortOrderByType.IndexOf(y.Type);

if (xSort < 0) xSort = int.MaxValue;
if (ySort < 0) ySort = int.MaxValue;


the index should never be less then zero. If it is, then there is an error. Its an enum and the property isn't nullable so I think the protection isn't necessary.

After getting ther RegionType order from the dictionary you should be able to immediately call this

return xSort.CompareTo(ySort);

Code Snippets

private static readonly List<RegionType> sortOrderByType = new List<RegionType>
{
    RegionType.DeletionBeforeNamedRegion,
    RegionType.NamedRegion,
    RegionType.DeletionWithinNamedRegion,
    RegionType.InsertionWithinNamedRegion,
    RegionType.DeletionAfterNamedRegion,
    RegionType.InsertionBetweenNamedRegions,
};
private static readonly Dictionary<RegionType, int> _regionTypeOrder = new RegionType[] 
{
    RegionType.DeletionBeforeNamedRegion,
    RegionType.NamedRegion,
    RegionType.DeletionWithinNamedRegion,
    RegionType.InsertionWithinNamedRegion,
    RegionType.DeletionAfterNamedRegion,
    RegionType.InsertionBetweenNamedRegions,
}
.Select((x, i) => new { Key = x, Order = i })
.ToDictionary(x => x.Key, x => x.Order);
var xSort = sortOrderByType.IndexOf(x.Type);
var ySort = sortOrderByType.IndexOf(y.Type);
var xSort = _regionTypeOrder[x.Type];
var ySort = _regionTypeOrder[y.Type];
var xSort = sortOrderByType.IndexOf(x.Type);
var ySort = sortOrderByType.IndexOf(y.Type);

if (xSort < 0) xSort = int.MaxValue;
if (ySort < 0) ySort = int.MaxValue;

Context

StackExchange Code Review Q#151534, answer score: 2

Revisions (0)

No revisions yet.