[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
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.
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:
Imports System.Text.RegularExpressions
Public Class NaturalComparer
Implements IComparer(Of String)
Private _pos As Integer
Private ReadOnly _order As Integer
Public Sub New(Optional Ascending As Boolean = True)
_order = If(Ascending, 1, -1)
End Sub
Private Shared Function RegexSplit(ByVal s As String) As String()
Return Regex.Split(s, "(\d+)", RegexOptions.IgnoreCase)
End Function
Private Shared Function GetEmptyStrings() As Predicate(Of String)
Return Function(s) String.IsNullOrEmpty(s)
End Function
Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
Dim left As New List(Of String)(RegexSplit(x))
Dim right As New List(Of String)(RegexSplit(y))
left.RemoveAll(GetEmptyStrings())
right.RemoveAll(GetEmptyStrings())
_pos = 0
For Each x In left
If y.Count > _pos Then
If Not Decimal.TryParse(x, Nothing) AndAlso Not Decimal.TryParse(right(_pos), Nothing) Then
Dim result As Integer = String.Compare(x, right(_pos), True)
If result <> 0 Then
Return result * _order
Else
_pos += 1
End If
ElseIf Decimal.TryParse(x, Nothing) AndAlso Not Decimal.TryParse(right(_pos), Nothing) Then
Return -1 * _order
ElseIf Not Decimal.TryParse(x, Nothing) AndAlso Decimal.TryParse(right(_pos), Nothing) Then
Return 1 * _order
Else
Dim result = Decimal.Compare(Decimal.Parse(x), Decimal.Parse(right(_pos)))
If result = 0 Then
_pos += 1
Else
Return result * _order
End If
End If
Else
Return -1 * _order
End If
Next
Return _order
End Function
End Class
Or using Api Methods.
vb.net Code:
Public Class ApiNaturalComparer
Implements IComparer(Of String)
Private Class NativeMethods
Public Declare Unicode Function StrCmpLogicalW Lib "shlwapi.dll" (s1 As String, s2 As String) As Integer
End Class
Private ReadOnly _order As Integer
Public Sub New(Optional IsAscending As Boolean = True)
_order = If(IsAscending, 1, -1)
End Sub
Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
Return NativeMethods.StrCmpLogicalW(x, y) * _order
End Function
End Class
Usage example of both options.
vb.net Code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim MyList = New List(Of String)({"ob1", "ob5", "ob2", "ob3", "ob33", "ob10", "ob1", "ob11", "ob123", "ob20"})
'MyList.Sort(New NaturalComparer(True))
'OutputListBox.Items.AddRange(MyList.ToArray())
MyList.Sort(New ApiNaturalComparer(True))
OutputListBox.Items.AddRange(MyList.ToArray())
End Sub
End Class
Re: [RESOLVED] Vb.net 2010 Sort List(of String) : String with Integer
thanQ Mattp ..itz working fine n once again thnx
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:
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 list = {"ob1", "ob5", "ob2", "ob3", "ob33", "ob10", "ob1", "ob11", "ob123", "ob20"}
Dim orderedList = list.OrderBy(Function(n) CInt(New Regex("(?<=.*)\d+").Match(n).Value)).ToArray
Me.ListBox1.Items.AddRange(orderedList)
End Sub
End Class
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
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:
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub SortArray(ByVal list() As String)
Me.ListBox1.Items.AddRange(
(
From item
In list Order By New Regex("[a-z]+").Match(item).Value,
CInt(New Regex("(?<=.*)\d+").Match(item).Value)
Select item).ToArray
)
End Sub
End Class
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