Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Custom sorting with ArrayList using IComparer

Last week, my colleague approached me for a help on sorting a list of string. Let's assume the data will be:

1C 2A 10B 9Z 2D

Let's break that into a string[] array using split and then you can choose to store in any collections for sorting. By default, when you sort with this way it will always based on the numbering sorting. You will probably get this result instead:

1C 2A 2D 9Z 10B // not sort by 1st number

Instead, he wanted to get this:

2A 10B 1C 2D 9Z // sort by the last alphabet

Let's analyze the requirement by looking at 2A:

2A // the 1st number is in between 1 - 10, the 2nd alphabet character is between A - Z, there will not occurence of the same alphabet in this string like 2A 3A

In order to solve this problem, I plan to build a custom IComparer. It might not be the best way to solve the problem. If you think there is a better way, do share with me. Thanks.

 Below is the code:

    1 using System;

    2 using System.Collections;

    3 

    4 namespace ConsoleApplication5

    5 {

    6     /// <summary>

    7     /// Using C# 3.0

    8     /// The features is nothing new

    9     /// Replace var with the actual data type, I am using VS 2008

   10     ///

   11     /// Developed by Chua Wen Ching

   12     /// </summary>

   13     class Class1

   14     {

   15         public static void Main()

   16         {

   17             // You can consider to use List<T> collection, for effective

   18             var arrayList = new ArrayList();

   19             // Customer's Input Buffer

   20             var inputFromLPM = "1C 2A 10B 9Z 2D";

   21 

   22             // Extract the character and assign to the LPMBuffer class, then into the ArrayList

   23             // Might not be the best way. Could be improved :)

   24             // There could not be duplicate A, example 2A 1A, it will show 2A 1A instead of 1A 2A

   25             // It is matter of coding, this is a good start for you.

   26             ProcessInputStringFromLPM(inputFromLPM, arrayList);

   27 

   28             // Use IComparer to do custom sorting

   29             arrayList.Sort(new LPMBufferComparer());

   30 

   31             // Display the result

   32             foreach (var o in arrayList)

   33                 Console.Write(o.ToString());

   34 

   35             Console.ReadLine();

   36         }

   37 

   38         private static void ProcessInputStringFromLPM(string inputFromLPM, IList arrayList)

   39         {

   40             // As Razie said earlier, each section is separated by a empty space

   41             var arrayFromString = inputFromLPM.Split(new char[] { ' ' });

   42 

   43             for (var i = 0; i < arrayFromString.Length; i++)

   44             {

   45                 var numValue = string.Empty;

   46                 var charValue = string.Empty;

   47                 short numDummy;

   48 

   49                 foreach (char c in arrayFromString[i])

   50                 {

   51                     if (short.TryParse(c.ToString(), out numDummy))

   52                     {

   53                         // If is number, assign here

   54                         numValue += numDummy;

   55                     }

   56                     else

   57                     {

   58                         // if is character, then assign here

   59                         charValue = c.ToString();

   60                     }

   61 

   62                 }

   63 

   64                 // Add LPMBuffer class and the values computed above here

   65                 arrayList.Add(new LPMBuffer(numValue, charValue));

   66             }

   67         }

   68     }

   69 

   70     /// <summary>

   71     /// Implements IComparer interface, will be use when you sort the arraylist

   72     /// </summary>

   73     class LPMBufferComparer : IComparer

   74     {

   75         int IComparer.Compare(object a, object b)

   76         {

   77             var b1 = (LPMBuffer)a;

   78             var b2 = (LPMBuffer)b;

   79             return string.Compare(b1.Last, b2.Last);

   80         }

   81     }

   82 

   83     class LPMBuffer : IComparable

   84     {

   85         public string First { get; set; }

   86         public string Last { get; set; }

   87 

   88         public LPMBuffer()

   89         {

   90 

   91         }

   92 

   93         public LPMBuffer(string first, string last)

   94         {

   95             this.First = first;

   96             this.Last = last;

   97         }

   98 

   99         // This is the actual comparison work

  100         int IComparable.CompareTo(object o)

  101         {

  102             var buffer = (LPMBuffer)o;

  103             return string.Compare(Last, buffer.Last);

  104         }

  105 

  106         // Display a inituitive output, can do anything you prefer here

  107         public override string ToString()

  108         {

  109             return First + ":" + Last + " ";

  110         }

  111     }

  112 }

2 Comments

  • That's a lot of code. &nbsp;I'd do it something like this:
    private static int CompareByLast(string x, string y)
    {
    &nbsp; &nbsp;// For simplicity don't handle nulls, we won't get them using String.Split
    &nbsp; &nbsp;char lastX = (x.Length == 0) ? '\0' : x[x.Length - 1];
    &nbsp; &nbsp;char lastY = (y.Length == 0) ? '\0' : y[y.Length - 1];
    &nbsp; &nbsp;return lastX.CompareTo(lastY);
    }
    static void Main()
    {
    &nbsp; &nbsp;...
    &nbsp; &nbsp;string inputFromLPM = "1C 2A 10B 9Z 2D";
    &nbsp; &nbsp;List&lt;string&gt; items = new List&lt;string&gt;(inputFromLPM.Split(' '));
    &nbsp; &nbsp;items.Sort(CompareByLast);
    &nbsp; &nbsp;...
    }

  • Interesting. Thanks Joe for the input :)

Comments have been disabled for this content.