How can I sort alphanumeric string list in C# (With & Without LINQ)?


I have a requirement in my project, in which I need to sort the string which has alphanumeric data like below

CA101
CA20
CBC11
CMC12

So, I Would like to know how to sort alphanumeric kind of list easily and efficiently in C#, with or without using LINQ?


Asked by:- jon
1
: 12641 At:- 7/10/2018 2:48:29 PM
C# alphanumeric sorting linq







2 Answers
profileImage Answered by:- vikas_jk

Here are the two ways to sort alphanumeric string in C#

First Method is using natural sort C# function

 /// <summary>
        /// Compares two sequences.
        /// </summary>
        /// <typeparam name="T">Type of item in the sequences.</typeparam>
        /// <remarks>
        /// Compares elements from the two input sequences in turn. If we
        /// run out of list before finding unequal elements, then the shorter
        /// list is deemed to be the lesser list.
        /// </remarks>
        public class EnumerableComparer<T> : IComparer<IEnumerable<T>>
        {
            /// <summary>
            /// Create a sequence comparer using the default comparer for T.
            /// </summary>
            public EnumerableComparer()
            {
                comp = Comparer<T>.Default;
            }

            /// <summary>
            /// Create a sequence comparer, using the specified item comparer
            /// for T.
            /// </summary>
            /// <param name="comparer">Comparer for comparing each pair of
            /// items from the sequences.</param>
            public EnumerableComparer(IComparer<T> comparer)
            {
                comp = comparer;
            }

            /// <summary>
            /// Object used for comparing each element.
            /// </summary>
            private IComparer<T> comp;


            /// <summary>
            /// Compare two sequences of T.
            /// </summary>
            /// <param name="x">First sequence.</param>
            /// <param name="y">Second sequence.</param>
            public int Compare(IEnumerable<T> x, IEnumerable<T> y)
            {
                using (IEnumerator<T> leftIt = x.GetEnumerator())
                using (IEnumerator<T> rightIt = y.GetEnumerator())
                {
                    while (true)
                    {
                        bool left = leftIt.MoveNext();
                        bool right = rightIt.MoveNext();

                        if (!(left || right)) return 0;

                        if (!left) return -1;
                        if (!right) return 1;

                        int itemResult = comp.Compare(leftIt.Current, rightIt.Current);
                        if (itemResult != 0) return itemResult;
                    }
                }
            }
        }

Second Method is to pad the numeric portion & use OrderBy Clause

public static string PadNumbers(string input)
{
    return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
}

above functions pads zeros for any number (or numbers) that appear in the input string

Here is the complete C# console app with both functions implemented in it

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SortingAlphaNumericString
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] testItems = { "CA101", "CA102", "CA11", "z1",
                       "z3", "z20", "z5", "z11",
                       "z21", "z22" };


            var SortedUsingPad = testItems.OrderBy(x => PadNumbers(x));
            Console.WriteLine("Sorted data using PadNumbers");
            foreach (var str in SortedUsingPad)
            {
                Console.WriteLine(str);
            }


            Func<string, object> convert = str =>
            {
                try { return int.Parse(str); }
                catch { return str; }
            };
            Console.WriteLine();

            var result = testItems.OrderBy(
                str => Regex.Split(str.Replace(" ", ""), "([0-9]+)").Select(convert),
                new EnumerableComparer<object>());

            Console.WriteLine("Sorted list using Natural sort");
            foreach(var str in result)
            {
                Console.WriteLine(str);
            }

           

           

        }
        /// <summary>
        /// Compares two sequences.
        /// </summary>
        /// <typeparam name="T">Type of item in the sequences.</typeparam>
        /// <remarks>
        /// Compares elements from the two input sequences in turn. If we
        /// run out of list before finding unequal elements, then the shorter
        /// list is deemed to be the lesser list.
        /// </remarks>
        public class EnumerableComparer<T> : IComparer<IEnumerable<T>>
        {
            /// <summary>
            /// Create a sequence comparer using the default comparer for T.
            /// </summary>
            public EnumerableComparer()
            {
                comp = Comparer<T>.Default;
            }

            /// <summary>
            /// Create a sequence comparer, using the specified item comparer
            /// for T.
            /// </summary>
            /// <param name="comparer">Comparer for comparing each pair of
            /// items from the sequences.</param>
            public EnumerableComparer(IComparer<T> comparer)
            {
                comp = comparer;
            }

            /// <summary>
            /// Object used for comparing each element.
            /// </summary>
            private IComparer<T> comp;


            /// <summary>
            /// Compare two sequences of T.
            /// </summary>
            /// <param name="x">First sequence.</param>
            /// <param name="y">Second sequence.</param>
            public int Compare(IEnumerable<T> x, IEnumerable<T> y)
            {
                using (IEnumerator<T> leftIt = x.GetEnumerator())
                using (IEnumerator<T> rightIt = y.GetEnumerator())
                {
                    while (true)
                    {
                        bool left = leftIt.MoveNext();
                        bool right = rightIt.MoveNext();

                        if (!(left || right)) return 0;

                        if (!left) return -1;
                        if (!right) return 1;

                        int itemResult = comp.Compare(leftIt.Current, rightIt.Current);
                        if (itemResult != 0) return itemResult;
                    }
                }
            }
        }


        public static string PadNumbers(string input)
        {
            return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
        }
    }
}

Output

alphanumeric-sorting-in-csharp-min.png

I will recommed to use natural sort method as, as pad numbers method will not when a string comes with space in between it like "z 12".

1
At:- 7/10/2018 6:48:01 PM Updated at:- 12/1/2022 7:52:27 AM
Thanks. 0
By : jon - at :- 7/12/2018 1:10:57 PM


profileImage Answered by:- vikas_jk

You can also simply use Lambda

 var result = YourList.OrderBy(x => PadNumbers(x));

Where PadNumbers

public static string PadNumbers(string input)
{
    return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
}

Thanks

0
At:- 9/27/2022 8:50:51 AM






Login/Register to answer
Or
Register directly by posting answer/details

Full Name *

Email *




By posting your answer you agree on privacy policy & terms of use