Sorting addresses treating numbers numerically

I was working on a small sorting task where we wanted to sort entries like these:

1 Sesame St
2 Sesame St
12 Sesame St
Building A
Building Z
Suite 1
Suite 2
Suite 100

As you can see this probably is what you’d expect ā€” the numerical parts of the strings are sorted numerically. But standard string and number sorts don’t do that. So I worked out a quick compare routine for using in sorting and thoughts I’d share it.

        public static int Compare(string a, string b)
        {
            var numberA = ""; 
            var numberB = "";
            int cmp, ap = 0, bp = 0;
            char ca, cb;

            while (ap < a.Length && bp < b.Length)
            {
                ca = a[ap];
                cb = b[bp];

                bool aDigit = Char.IsDigit(ca);
                bool bDigit = Char.IsDigit(cb);

                if (aDigit && bDigit)
                {
                    // Create a number from all contiguous digits in string a
                    do
                    {
                        numberA += ca;
                        ap++;

                    } while (ap < a.Length && Char.IsDigit(ca = a[ap]));

                    // Same for string b
                    do
                    {
                        numberB += cb;
                        bp++;

                    } while (bp < b.Length && Char.IsDigit(cb = b[bp]));

                    // Compare the numbers numerically
                    cmp = Int32.Parse(numberA) - Int32.Parse(numberB);
                    if (cmp != 0)
                    {
                        return cmp;
                    }
                    numberA = numberB = "";
                
                    // If they match look at the characters following them
                    cmp = ca - cb;
                    if (cmp != 0)
                    {
                        return cmp;
                    }
                    ap++;
                    bp++;
                }

                else if (aDigit)
                {
                    return -1;
                }
                else if (bDigit)
                {
                    return 1;
                }
                else
                {
                    cmp = ca - cb;
                    if (cmp != 0)
                    {
                        return cmp;
                    }
                    ap++;
                    bp++;    
                }

            }

            return a.Length - b.Length;
        }

I have to apologize that there’s no test code for this. But I hope it’s helpful to some. Should be easy enough to translate to other languages.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s