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 }