Feedel
Feedel

Reputation: 163

vb.net - List (Of String) Sorting, Numbers Ascending, Alphabet Descending

I am trying to sort a list of string into a very particular order. I have a list of items which come in the format of "X123XXX" where X can be a letter, and the 123 can be any number.

Dim AList As New List(Of String)
AList.Add("B200")
AList.Add("A100X")
AList.Add("A100XY")
AList.Add("A100XYZ")

AList.Sort()

'Actual Return in order (AList(1).tostring etc.)
'A100X
'A100XY
'A100XYZ
'B200

'Desired Return
'A100XYZ
'A100XY
'A100X
'B200

The problem I have is that Not only do I need to sort the Numbers Ascending and Letters Descending, but I also need to sort the first letter Ascending.

I was hoping that, as the parts are always in the same format (letter + 3 numbers + Optional up to 3 letters) - that I could just select the first 4 and sort that ASC and then DESC on the last 3. But i have no idea how to do that in vb.net. I've had a look around, and can only find the IComparable stuff, which doesn't seem like it would be very useful.

Upvotes: 2

Views: 6282

Answers (2)

theB
theB

Reputation: 6738

An alternate approach to the anonymous function, create a Class that implements IComparer(Of String):

Private Class CodeComparer
    Implements System.Collections.Generic.IComparer(Of String)

    Function Compare(ByVal a As String, ByVal b As String) As Integer _
             Implements IComparer(Of String).Compare
        Dim result As Integer = a.Substring(0, 4).CompareTo(b.Substring(0, 4))
        If result = 0 Then
            result = a.Substring(4).CompareTo(b.Substring(4)) * -1
        End If
        Return result
    End Function
End Class

This sorts by the first 4 characters in ascending order, then by the remaining characters in decending order (hence the * -1).

You can then sort the list using:

items.Sort(New CodeComparer())

Edit: You can also use the same algorithm with an anonymous function passed to the Sort method.

items.Sort(Function(a, b)
               Dim result As Integer = a.Substring(0, 4).CompareTo(b.Substring(0, 4))
               If result = 0 Then result = a.Substring(4).CompareTo(b.Substring(4)) * -1
               Return tmp
           End Function)

Upvotes: 2

user2480047
user2480047

Reputation:

You can get what you want by relying on some LINQ methods (OrderBy, ThenBy, etc.); they allow you to perform all the modifications you need.

Code delivering what you want:

 AList = AList.OrderBy(Function(x) x.Substring(0, 1)).ThenBy(Function(x) Convert.ToInt32(x.Substring(1, 3))).ThenByDescending(Function(x) x.Substring(4)).ToList()

UPDATE

The code above orders the last part (i.e., letters from the 5th position until the end) in alphabetically descending order; but apparently the OP wants this last sorting to be performed on account of the length of the strings (i.e., longest one first and shortest one last). The following code delivers such a behaviour:

AList = AList.OrderBy(Function(x) x.Substring(0, 1)).ThenBy(Function(x) Convert.ToInt32(x.Substring(1, 3))).ThenByDescending(Function(x) x.Substring(4).Length).ToList()

Upvotes: 5

Related Questions