Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Algorithm for Alphanumerical Sort with IComparer

5.00/5 (1 vote)
15 Jun 2015CPOL1 min read 6.8K  
An algorithm for sort alphanumerical strings in their own natural way

Introduction

So I hope I do not have to explain how IComparer works... just a very quick briefing for those who are not aware.

Most collections and controls of VB.NET give the possibility to define an own control logic. For example, if you want to sort an arraylist that contains other small arrays, you can implement your logic and define that he has to compare the first and the second element of the "jagged" array. Otherwise, if you are a very good coder, but I think you are not going to read this article, you can decide to sort for shades of red some pictures. This is not the case, I would just implement an efficient routine to sort alphanumerically so that the item "WPS-9" is smaller than "WPS-10". This should not be true with the default sorter of .NET. 

Using the Code

The controls and classes have a method to implement the Icomparer:

VB.NET
TreeView1.TreeViewNodeSorter=new TreeSorter 'TreeSorter is the class below
LisView1.ListViewItemSorter  ' and others

You have just to build a class that implements that Interface Icompare (you need just to write Implements IComparer under the declaration of the class) and this class must implement the method Compare (you need just to specify after the declaration of the function  Implements Icomparer.Compare).

And here is the algorithm:

VB.NET
Public Class TreeSorter
    Implements System.Collections.IComparer
    Private obcomparer As New CaseInsensitiveComparer

    Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements System.Collections.IComparer.Compare
        Dim tx As TreeNode = CType(x, TreeNode)
        Dim ty As TreeNode = CType(y, TreeNode)
        Dim nx, ny As New System.Text.StringBuilder
        Dim cx(), cy() As Char
        cx = tx.Text.ToLower.ToCharArray
        cy = ty.Text.ToLower.ToCharArray
        If tx.Text.Length = 0 Then Return -1
        If ty.Text.Length = 0 Then Return 1
        Dim xl, yl, i, j As Integer
        xl = UBound(cx)
        yl = UBound(cy)   

        Dim tempX, tempY As Integer

        Do
            'if finds some number read the whole number

            Do While i <= xl AndAlso Char.IsDigit(cx(i))
                nx.Append(cx(i))
                i += 1
            Loop
            'the same as above but for the other string
            Do While j <= yl AndAlso Char.IsDigit(cy(j))
                ny.Append(cy(j))
                j += 1
            Loop

            If nx.Length > 0 Then ' if found some number in the x.text
                If ny.Length = 0 Then Return -1 ' but not in the second
                'the texts are not balanced therefore we can say that x is smaller than y
                tempX = Convert.ToInt32(nx.ToString)
                tempY = Convert.ToInt32(ny.ToString)

                If tempX > tempY Then Return 1 'confront the numbers
                If tempX < tempY Then Return -1

                ' this code is for the special case some text end with number but the other 
                'part continue
                If i > xl Then
                    If j > yl Then Return 0
                    Return -1
                End If
                If j > yl Then Return 1
                'nope both strings are still the same. Reset the counters
                nx = New System.Text.StringBuilder
                ny = New System.Text.StringBuilder
            End If
            If ny.Length > 0 Then Return 1 'if found some numbers in the y.text
            ' and for sure it did not found in the x text as above we can say x is greater than y

            'now we can compare the not numeric chars
            If cx(i) <> cy(j) Then Return String.Compare(cx(i), cy(j))

            If i < xl Then
                i += 1
                If j < yl Then
                    j += 1
                Else
                    Return 1 'if comes here means that y is shorter than x 
                End If
            Else
                If j < yl Then
                    Return -1 'vice-versa x is shorter than y
                Else
                    Return 0 'both rows are at the and and there is no greater
                End If

            End If

        Loop

    End Function
End Class  

Points of Interest

It is fast. It compares the strings char by char, so at the first difference it returns instantly. Enjoy it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)