Back to Blog

How to sort alphanumeric values with jQuery and C#

October 25, 2012

By Matt Mombrea
No Comments

Sorting values on the server side is usually pretty trivial. There are a lot of tools at your disposal, not the least of which is the data query itself. When it comes to sorting an element on the front end however, it can sometimes take a little bit of clever data value usage to accomplish your goal, especially if you don’t want to make another call to the server.

For this example, let’s assume that we have a list of visitors staying at a hotel. Each visitor has a visit with basic data describing that visit, such as their name, room number, length of stay, etc. Imagine that you are laying out each of those current visits on a web application dashboard for a quick view of who is staying at the hotel at the moment. Each visit might be represented by a 200 x 200 block of data that we might call a ‘card’. Initially these cards might be sorted by Last Name but say you want to change that sort order so that it is ordered by Room Number instead. If your room numbers are plain integers this is pretty easy, but what if they consist of letters,numbers, and other special characters? For example, 407 W to represent the west wing of the building.

When I need to do some element sorting using jQuery I turn to TinySort, the fantastic plugin by Ron Valstar. It is very flexible, well documented, and at just 1kB gzipped, tiny. Out of the box, TinySort does some very good sorting, even on mixed literal and numeric strings. For example (from the TinySort docs):

mixed literal and numeral

In a normal sort the order would be a1,a11,a2 while you’d really want it to be a1,a2,a11. TinySort corrects this:

$(".visit-list ul li").tsort();
  • eed140ler111
  • eil26viu117
  • omi111jea23
  • uin115oem6
  • uin1oem121
  • uin37oem109
  • uin84oem57
  • uin84oem78
  • uin84oem88

In my use however, I was unable to get the proper sort order when numbers were followed by a blank space, then a letter, i.e “407 W”. To correct this, and to gain more control of how the objects would be sorted, I decided to use TinySort’s ability to specify what attribute I’d like to sort on. I created a custom HTML5 data element called data-room and told TinySort to use the value of that attribute when sorting:

$(".visit-list ul li").tsort({ attr: 'data-room'});

Then in my HTML I use that data element on the objects I want to sort:

<div class="visit-list">
    <ul>
        <li data-room="404 W">
            Visit Details
        </li>
    </ul>
 </div>

The next step is to control the value of that data-room attribute more precisely. In this example I’m using C#.NET MVC 4 with the Razor view engine on the server side. I want to convert the room number into a more basic form, in my case I decided to turn everything into a decimal for easy sorting. To do this, I created an extension method so that I’d have access to it conveniently throughout my application. The extension method looks like this:

        public static decimal ToSortableDecimal(this string str)
        {
            if (String.IsNullOrWhiteSpace(str))
                return 0;

            char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

            StringBuilder sb = new StringBuilder();
            foreach (var c in str.ToUpper().ToCharArray())
            {
                int result;
                if (int.TryParse(c.ToString(), out result))
                {
                    sb.Append(c);
                }
                else
                {
                    if (c == ' ' || Array.IndexOf(alpha, c) == -1)
                    { //ignore
                    }
                    else
                    {
                        if (!sb.ToString().Contains('.'))
                            sb.Append(".");

                        sb.Append(Array.IndexOf(alpha, c));
                    }
                }
            }
            return decimal.Parse(sb.ToString());
        }

When you pass a string through this function, several things happen:

  • All non alphanumeric characters are eliminated
  • If a numeric character is encountered, it is added to the decimal at the current position
  • If a letter is encountered, a decimal is added if one does not yet exist
  • If a letter is encountered, it’s position in the alphabet is determined and that index position is used in place of the letter

For example, “0965 D” becomes “965.3” which is much easier to sort and a lot more clear in terms of how the sort will behave.

Now you just need to use this room number conversion in the HTML:

<div class="visit-list">
    <ul>
        @foreach (var visit in Model.Visits)
        {
            <li data-room="@visit.RoomNumber.ToSortableDecimal()">
                Visit Details
            </li>
        }
    </ul>
</div>

When you trigger TinySort on those elements, you will get a nice, tidy decimal sort.

Matt Mombrea

Matt Mombrea

Matt is a longtime entrepreneur and software engineer. He also sits on the board of Computer Science at SUNY Fredonia. Born and raised in Buffalo, Matt is passionate about building and maintaining great businesses in Buffalo. Apart from leading Cypress North, Matt architects our company’s datacenter, engineers dozens of custom applications, and directs the rest of the development team.

See Matt's Most Recent Posts

Share this post

Leave a Reply

Search our blog

Start A Project

Categories

What's next?

Well...you might like one of these

Article

Is Google Analytics 4 a Tactical Move...

There’s something fishy going on with the way that Google...

Read article

Article

How We Build It: Website Process with...

This month, I sat down with Matt Mombrea, Chief Technical...

Read article

Article

[SOLVED] Using an in-memory repository....

.NET Core Data Protection One of the main benefits of...

Read article