Results 1 to 8 of 8

Thread: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

  1. #1

    Thread Starter
    Member
    Join Date
    Oct 2011
    Posts
    60

    Resolved [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    Hello Genius :
    can you help me how to sort string in List(of String)
    my code is

    PHP Code:
        Dim _lst As List(Of String) = New List(Of String)({"ob1""ob5""ob2""ob3""ob33""ob10""ob1""ob11""ob123""ob20"})
                
    _lst.Sort()
                
    ListBox1.Items.AddRange(_lst.ToArray
    Result is like :=
    PHP Code:
    ob1
    ob1
    ob10
    ob11
    ob123
    ob2
    ob20
    ob3
    ob33
    ob5 
    but i want to result like this :=
    PHP Code:
     ob1,ob1,ob2,ob3,.......... 
    how to sort like this please help me l'm struggled

    Thanks

  2. #2
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Vb.net 2010 Sort List(of String) : String with Integer

    The fault lies with the strings not with the sorting. Reference codes such as these should always be formatted to be of the same length. So if your highest reference is ob999, your first should be ob001. This requires nothing but a simple alphabetical sort. If you are unable to produce values in this form because your getting them from a third party, for example, you could attempt a sorting algorithm but assuming you want to avoid potential insanity it would be far simpler to reformat the values using string manipulation methods.
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  3. #3
    Frenzied Member MattP's Avatar
    Join Date
    Dec 2008
    Location
    WY
    Posts
    1,227

    Re: Vb.net 2010 Sort List(of String) : String with Integer

    You'll need to have a Natural Comparison of the strings to get what you're looking for.

    Here's a couple of options.

    vb.net Code:
    1. Imports System.Text.RegularExpressions
    2.  
    3. Public Class NaturalComparer
    4.     Implements IComparer(Of String)
    5.  
    6.     Private _pos As Integer
    7.     Private ReadOnly _order As Integer
    8.  
    9.     Public Sub New(Optional Ascending As Boolean = True)
    10.         _order = If(Ascending, 1, -1)
    11.     End Sub
    12.  
    13.     Private Shared Function RegexSplit(ByVal s As String) As String()
    14.         Return Regex.Split(s, "(\d+)", RegexOptions.IgnoreCase)
    15.     End Function
    16.  
    17.     Private Shared Function GetEmptyStrings() As Predicate(Of String)
    18.         Return Function(s) String.IsNullOrEmpty(s)
    19.     End Function
    20.  
    21.     Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
    22.         Dim left As New List(Of String)(RegexSplit(x))
    23.         Dim right As New List(Of String)(RegexSplit(y))
    24.  
    25.         left.RemoveAll(GetEmptyStrings())
    26.         right.RemoveAll(GetEmptyStrings())
    27.  
    28.         _pos = 0
    29.         For Each x In left
    30.             If y.Count > _pos Then
    31.                 If Not Decimal.TryParse(x, Nothing) AndAlso Not Decimal.TryParse(right(_pos), Nothing) Then
    32.                     Dim result As Integer = String.Compare(x, right(_pos), True)
    33.                     If result <> 0 Then
    34.                         Return result * _order
    35.                     Else
    36.                         _pos += 1
    37.                     End If
    38.                 ElseIf Decimal.TryParse(x, Nothing) AndAlso Not Decimal.TryParse(right(_pos), Nothing) Then
    39.                     Return -1 * _order
    40.                 ElseIf Not Decimal.TryParse(x, Nothing) AndAlso Decimal.TryParse(right(_pos), Nothing) Then
    41.                     Return 1 * _order
    42.                 Else
    43.                     Dim result = Decimal.Compare(Decimal.Parse(x), Decimal.Parse(right(_pos)))
    44.                     If result = 0 Then
    45.                         _pos += 1
    46.                     Else
    47.                         Return result * _order
    48.                     End If
    49.                 End If
    50.             Else
    51.                 Return -1 * _order
    52.             End If
    53.         Next
    54.  
    55.         Return _order
    56.     End Function
    57. End Class

    Or using Api Methods.

    vb.net Code:
    1. Public Class ApiNaturalComparer
    2.     Implements IComparer(Of String)
    3.  
    4.     Private Class NativeMethods
    5.         Public Declare Unicode Function StrCmpLogicalW Lib "shlwapi.dll" (s1 As String, s2 As String) As Integer
    6.     End Class
    7.  
    8.     Private ReadOnly _order As Integer
    9.  
    10.     Public Sub New(Optional IsAscending As Boolean = True)
    11.         _order = If(IsAscending, 1, -1)
    12.     End Sub
    13.  
    14.     Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
    15.         Return NativeMethods.StrCmpLogicalW(x, y) * _order
    16.     End Function
    17. End Class

    Usage example of both options.

    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4.         Dim MyList = New List(Of String)({"ob1", "ob5", "ob2", "ob3", "ob33", "ob10", "ob1", "ob11", "ob123", "ob20"})
    5.         'MyList.Sort(New NaturalComparer(True))
    6.         'OutputListBox.Items.AddRange(MyList.ToArray())
    7.  
    8.         MyList.Sort(New ApiNaturalComparer(True))
    9.         OutputListBox.Items.AddRange(MyList.ToArray())
    10.     End Sub
    11. End Class
    This pattern in common to all great programmers I know: they're not experts in something as much as experts in becoming experts in something.

    The best programming advice I ever got was to spend my entire career becoming educable. And I suggest you do the same.

  4. #4

    Thread Starter
    Member
    Join Date
    Oct 2011
    Posts
    60

    Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    thanQ Mattp ..itz working fine n once again thnx

  5. #5
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    I know it's resolved but another approach with regex. Rather then splitting i think it be more suited to match the number and sort by that.

    vb Code:
    1. Imports System.Text.RegularExpressions
    2.  
    3. Public Class Form1
    4.  
    5.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    6.         Dim list = {"ob1", "ob5", "ob2", "ob3", "ob33", "ob10", "ob1", "ob11", "ob123", "ob20"}
    7.         Dim orderedList = list.OrderBy(Function(n) CInt(New Regex("(?<=.*)\d+").Match(n).Value)).ToArray
    8.         Me.ListBox1.Items.AddRange(orderedList)
    9.     End Sub
    10.  
    11. End Class

  6. #6
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,467

    Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    here's my effort. it'll work with any strings in that format (1 or more letters followed by 1 or more digit):

    Code:
    Imports System.Text.RegularExpressions
    
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim _lst As List(Of String) = New List(Of String)(New String() {"bc1", "bc5", "bc2", "bc3", "bc33", "bc10", "bc1", "bc11", "bc123", "bc20", "ab1", "ab5", "ab2", "ab3", "ab33", "ab10", "ab1", "ab11", "ab123", "ab20"})
            _lst.Sort(New comparer)
            ListBox1.Items.AddRange(_lst.ToArray)
        End Sub
    End Class
    
    Public Class comparer
        Implements IComparer(Of String)
    
        Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements System.Collections.Generic.IComparer(Of String).Compare
            Dim matches() As Match = {New Regex("^(?<textPart>[A-Za-z]+)(?<numericPart>\d+)$").Match(x), New Regex("^(?<textPart>[A-Za-z]+)(?<numericPart>\d+)$").Match(y)}
            Dim xParts() As String = matches(0).Groups.Cast(Of Group).Skip(1).Select(Function(g) g.Value).ToArray
            Dim yParts() As String = matches(1).Groups.Cast(Of Group).Skip(1).Select(Function(g) g.Value).ToArray
    
            If xParts(0) = yParts(0) Then
                Return CInt(xParts(1)).CompareTo(CInt(yParts(1)))
            Else
                Return xParts(0).CompareTo(yParts(0))
            End If
    
        End Function
    End Class

  7. #7
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    Another attempt supporting sorting of letters.... I'm purposely ignoring the IComparer class.


    vb Code:
    1. Imports System.Text.RegularExpressions
    2.  
    3. Public Class Form1
    4.  
    5.     Private Sub SortArray(ByVal list() As String)
    6.         Me.ListBox1.Items.AddRange(
    7.             (
    8.                 From item
    9.                 In list Order By New Regex("[a-z]+").Match(item).Value,
    10.                 CInt(New Regex("(?<=.*)\d+").Match(item).Value)
    11.                 Select item).ToArray
    12.             )
    13.     End Sub
    14.  
    15.  
    16. End Class

  8. #8
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer

    you wouldn't create a new instance of regex each time like i provided though

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width