|
-
May 3rd, 2012, 08:45 AM
#1
Thread Starter
Addicted Member
[RESOLVED] String Sorting
I have a list of strings lets say the items are like this
item_1
item_2
item_4
item_10
item_8
item_11
if i do list.sort() i get the following
item_1
item_10
item_11
item_2
item_4
item_8
Somehow i need to get these in order numerically but im dealing with strings not numbers.
-
May 3rd, 2012, 08:53 AM
#2
Re: String Sorting
yeah, that's an effect of strings... the only way to combat it is to pad with 0's....
so your list looks like this:
item_01
item_10
item_11
item_02
item_04
item_08
then sort it:
item_01
item_02
item_04
item_08
item_10
item_11
That's assuming that you have control over the strings.
-tg
edit - strike that... it isn't the ONLY way... but it's usually the easiest... there maybe other ways by implementing your own sorter (somethign I don't have experience with, but others here do) which could break the string up, then return results based on the numerical portion. Bit more work to setup, but probably more elegant, and if the string are not in your control, propbably your best bet.
-
May 3rd, 2012, 08:57 AM
#3
Hyperactive Member
Re: String Sorting
thats because they are being sorted as if they were strings, not as integers. If this were an array or collection you could have two "columns" one with the string value the other with its corresponding integer value. then sort on the integer value. example is using a sorted dictionary:
Code:
Dim myCollection As New SortedDictionary(Of String, Integer)
myCollection.add("item_1", 1)
myCollection.add("item_2", 2)
if i was able to help, rate my post!
-
May 3rd, 2012, 09:37 AM
#4
Re: String Sorting
For natural sorting you'll need to implement your own IComparer(Of String).
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
Here's a small example:
vb.net Code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim itemList As New List(Of String) From {"item_1", "item_2", "item_4", "item_10", "item_8", "item_11"}
itemList.Sort(New NaturalComparer(True))
End Sub
You could also use: pinvoke strcmplogicalw
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.
-
May 3rd, 2012, 11:23 AM
#5
Re: String Sorting
Another thing to consider is whether those strings work best as strings. I was working on a similar issue where the strings in question were names that included numbers in them. I sometimes needed to sort the numbers, sometimes the strings, and usually a combination of both. At first I went with the approach that MattP showed. However, as the problem evolved, I determined that the names had to be generated dynamically, and no custom sorter would necessarily work for all the variations that were desired. What I ended up doing was turning the names into a small class that had a string portion, a number portion....another string portion, and finally an ordinal. The class had .ToString overloaded, so that I could get the whole name back out so that it looked nice, but I could do some pretty complex sorting. Often I sorted by the number and the second string, but I could also sort by the ordinal, even though that wasn't visible. That allowed for a huge variety of sorted results.
My usual boring signature: Nothing
 
-
May 3rd, 2012, 11:38 AM
#6
Lively Member
Re: String Sorting
Hello
Another Easy Solution By LINQ
Code:
Dim Lst = (From Item As String In ListBox1.Items Select Item Order By Val(Item.Split("_")(1)) Ascending).ToArray
ListBox1.Items.Clear()
ListBox1.Items.AddRange(Lst)
All The Best 
Mohammad Farah
-
May 3rd, 2012, 11:47 AM
#7
Re: String Sorting
 Originally Posted by SNIPER.PS
Hello
Another Easy Solution By LINQ
Code:
Dim Lst = (From Item As String In ListBox1.Items Select Item Order By Val(Item.Split("_")(1)) Ascending).ToArray
ListBox1.Items.Clear()
ListBox1.Items.AddRange(Lst)
All The Best
Mohammad Farah
This makes the assumption that everything before the underscore will be the same. If the list contains 2 items abc_5 and xyz_1 natural sorting would have the abc_5 first.
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.
-
May 3rd, 2012, 12:13 PM
#8
Lively Member
Re: String Sorting
 Originally Posted by MattP
This makes the assumption that everything before the underscore will be the same. If the list contains 2 items abc_5 and xyz_1 natural sorting would have the abc_5 first.
Hello
Thanks , You are right .. and the code after edited will be
Code:
Dim Lst = (From Item As String In ListBox1.Items Select Item Order By Item.Split("_")(0) Ascending, Val(Item.Split("_")(1)) Ascending).ToArray
ListBox1.Items.Clear()
ListBox1.Items.AddRange(Lst)
All The Best 
Mohammad Farah
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|