Wednesday, February 10, 2016

A small alfanumeric sorter with numeric padding

I just got a support task where I’m pulling data from an API and need to sort the items based on a chapter like key. The data looks like this:

  • ST.1.1
  • ST.1.2
  • ST.1.10
  • ST.2.20a

The data is coming back random, and if I do a pure alfanumeric sorter, then ST.1.10 will sort above ST.1.2, which is lexically incorrect. Since I know I will never have numbers above three digits (ST.999.999), I figured I could sort it all by padding the numbers. This is the solution I ended up with, and if you have a smarter one let me know :)

I’m matching right to left in the regular expression as this makes it easier to replace the string as indexes are not changed when inserting characters.

class Program
{
    static void Main()
    {
        var demo = new List<string> { "ST.1.1", "ST.1.10", "ST.1.3c", "ST.1.3a", "ST.1.2" };
        demo = demo.OrderBy(PadName).ToList();
        demo.ForEach(Console.WriteLine);
        //output is: ST.1.1 ST.1.2 ST.1.3a ST.1.3c ST.1.10
    }

    static readonly Regex _reNumber =
       new Regex(@"\d+", RegexOptions.Compiled | RegexOptions.RightToLeft);
    static string PadName(string name)
    {
        foreach (Match match in _reNumber.Matches(name))
        {
            string newNumber = match.Value.PadLeft(3, '0');
            name = name.Remove(match.Index, match.Length)
                       .Insert(match.Index, newNumber);
        }
        return name;
    }
}