הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Thursday, April 26, 2012 9:51 PM
I have looked, unsuccessfully, for how to sort a list of strings alpha numerically. The .Sort() method sorts it like so:
abc,abc1,abc11,abc12,abc2,abc21,abc22
I don't want it sorted that way, I want it sorted like so:
abc,abc1,abc2,abc11,abc12,abc21,abc22
Any Ideas?
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
All replies (17)
Friday, April 27, 2012 9:45 PM ✅Answered
I have given up on sorting like this.
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
Thursday, April 26, 2012 10:06 PM
Use your own Comparer.
Thursday, April 26, 2012 10:09 PM
You can use LINQ to obtain the collection ordered as you want:
Dim orderedList = _
{"abc", "abc1", "abc2", "abc11", "abc12", "abc21", "abc22" } _
.OrderBy(Function(x) Integer.Parse("0" & x.Substring(3)))
Matteo Migliore
Bloghttp://blogs.ugidotnet.org/matteomigliore
Twitterhttp://twitter.com/matteomigliore
CodePlex
http://hyperionsdk.codeplex.com http://sample.codeplex.com
Thursday, April 26, 2012 10:11 PM
What if I don't know what the strings are?
My Code:
loc = fileOpener.FileName.Remove(fileOpener.FileName.LastIndexOf("\"))
For Each file As String In FileIO.FileSystem.GetFiles(loc)
If Regex.Matches(file, picPattern, RegexOptions.IgnoreCase).Count > 0 Then
files.Add(file)
End If
Next
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
Thursday, April 26, 2012 10:39 PM
"What if I don't know what the strings are?"
Your Comparer will return the desired result for any input.
Thursday, April 26, 2012 10:49 PM
You can solve with this snippet:
Dim orderedList = { "abc", "abc1", "abc2", "abc11", "abc12", "abc21", "abc22" } _
.Select(Function(x) New With {Key .Index = FirstNumberIndex(x), Key .Value = x}) _
.Select(Function(x) New With {Key .Value = x.Value, Key .Text = x.Value.Substring(0, x.Index), Key .Number = If(x.Index = x.Value.Length, 0, Integer.Parse(x.Value.Substring(x.Index)))}) _
.OrderBy(Function(x) x.Text).ThenBy(Function(x) x.Number) _
.Select(Function(x) x.Value)
Public Function FirstNumberIndex(ByVal value As String) As Integer
Dim index = 0
Dim found = value.Length
Do While index < value.Length
If Char.IsDigit(value.Chars(index)) Then
found = index
Exit Do
End If
index += 1
Loop
Return found
End Function
Matteo Migliore
Bloghttp://blogs.ugidotnet.org/matteomigliore
Twitterhttp://twitter.com/matteomigliore
CodePlex
http://hyperionsdk.codeplex.com http://sample.codeplex.com
Friday, April 27, 2012 2:59 AM
Dim orderedList = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "a", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", "a16", "a17", "a18", "a19", "a20", "b", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", "b16", "b17", "b18", "b19", "b20"}.Select(Function(x) New With {Key .Index = FirstNumberIndex(x), Key .Value = x}).Select(Function(x) New With {Key .Value = x.Value, Key .Text = x.Value.Substring(0, x.Index), Key .Number = If(x.Index = x.Value.Length, 0, Integer.Parse(x.Value.Substring(x.Index)))}).OrderBy(Function(x) x.Text).ThenBy(Function(x) x.Number).Select(Function(x) x.Value)
For Each file As String In FileIO.FileSystem.GetFiles(loc)
If Regex.Matches(file, picPattern, RegexOptions.IgnoreCase).Count > 0 Then
files.Add(file)
End If
Next
files.Sort(orderedList)
For Each file As String In files
If file = fileOpener.FileName Then
fileIndex = files.IndexOf(file)
Exit For
End If
Next
Conversion from type 'WhereSelectEnumerableIterator(Of VB$AnonymousType_1(Of String,String,Integer),String)' to type 'IComparer(Of String)' is not valid.
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
Friday, April 27, 2012 5:28 AM
Alpha numerical is a statement from before 1960 when we had punch cards.
We can sort only on numbers or on characters currently. For that you have to make your own logic using the by John already mentioned comparer.
http://msdn.microsoft.com/en-us/library/system.collections.comparer.aspx
There is simply no default logic for sorting an alpha string like this (be aware we are not living in 1960 anymore when 7 bits was already much) {十一,2,A0}
Success
Cor
Friday, April 27, 2012 5:34 AM
Cor,
"Alpha numerical is a statement from before 1960 when we had punch cards."....
This statement is incorrect. Alphanumerical is a label about data.....that's all.
Sophisticated places still use it.
Renee
"MODERN PROGRAMMING is deficient in elementary ways BECAUSE of problems INTRODUCED by MODERN PROGRAMMING." Me
Friday, April 27, 2012 7:27 AM
Cor,
"Alpha numerical is a statement from before 1960 when we had punch cards."....
This statement is incorrect. Alphanumerical is a label about data.....that's all.
Renee
Renee,
I don't think this statement is correct
Alpha numerical is a statement from behind 1960.
But if you say so, in this case I leave that to you.
:-)
Success
Cor
Friday, April 27, 2012 8:06 AM
Alphanumeric was an adjective used during the 60's, 70's, 80's and nineties and beyond BEFORE we got to MS candy....
Renee
"MODERN PROGRAMMING is deficient in elementary ways BECAUSE of problems INTRODUCED by MODERN PROGRAMMING." Me
Friday, April 27, 2012 8:19 AM
Like JohnWein had written, use your own comparer class.
Comparer class: http://msdn.microsoft.com/en-us/library/15ycttyf.aspx
IComparer interface: http://msdn.microsoft.com/en-us/library/system.collections.icomparer(v=vs.100).aspx
Hannes
If you have got questions about this, just ask.
In a perfect world,
users would never enter data in the wrong form,
files they choose to open would always exist
and code would never have bugs.
C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/
Friday, April 27, 2012 9:21 AM
Public Class Form1
Dim S() As String = "abc,abc1,abc11,abc12,abc2,abc21,abc22".Split(","c)
Dim L As New AlphanumericSortedList
Protected Overrides Sub OnLoad(e As System.EventArgs)
MyBase.OnLoad(e)
L.AddRange(S)
Console.Write("Before sort ")
OutputToConsole()
L.Sort(L)
Console.Write("After sort ")
OutputToConsole()
End Sub
Sub OutputToConsole()
For I As Integer = 0 To L.Count - 1
Console.Write(L(I).ToString + " ")
Next
Console.WriteLine()
End Sub
End Class
Class AlphanumericSortedList
Inherits List(Of String)
Implements IComparer(Of String)
Public Function Compare(X As String, Y As String) As Integer Implements IComparer(Of String).Compare
Dim C, I, J, IX, IY As Integer
For I = 0 To X.Length - 1
Dim S As String = X.Substring(I)
If Integer.TryParse(X.Substring(I), IX) Then Exit For
Next
For J = 0 To Y.Length - 1
Dim S As String = Y.Substring(J)
If Integer.TryParse(Y.Substring(J), IY) Then Exit For
Next
C = String.Compare(X.Substring(0, I), Y.Substring(0, J))
If C = 0 Then C = If(IX < IY, -1, If(IX = IY, 0, 1))
Return C
End Function
End Class
Needed to waste some time.
Friday, April 27, 2012 8:32 PM
it sorts it the same way: a, a1, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a2, a20, ect.
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
Friday, April 27, 2012 9:02 PM
The code I posted gives this output:
Before sort abc abc1 abc11 abc12 abc2 abc21 abc22
After sort abc abc1 abc2 abc11 abc12 abc21 abc22
Before sort a a1 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a2 a20
After sort a a1 a2 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20
Did you want something different?
Friday, April 27, 2012 9:10 PM
it didn't work for me.
Imports System.Text.RegularExpressions
Imports System.Net.Mail
Public Class Form1
Dim img As Image
Dim iH As Int32
Dim iW As Int32
Dim hH As Int32
Dim hW As Int32
Dim fWinState As FormWindowState
Dim m_Coordnates As Point
Dim files As List(Of String) = New List(Of String)
Dim sorter As New AlphanumericSortedList
Dim fileIndex As Int32
Dim loc As String
Dim picPattern As String = "^(.*)(\.(gif|jfif|jpe|jpeg|jpg|tif|tiff|bmp|dib|png))$"
Dim orderedList = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "a", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", "a16", "a17", "a18", "a19", "a20", "b", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", "b16", "b17", "b18", "b19", "b20"}.Select(Function(x) New With {Key .Index = FirstNumberIndex(x), Key .Value = x}).Select(Function(x) New With {Key .Value = x.Value, Key .Text = x.Value.Substring(0, x.Index), Key .Number = If(x.Index = x.Value.Length, 0, Integer.Parse(x.Value.Substring(x.Index)))}).OrderBy(Function(x) x.Text).ThenBy(Function(x) x.Number).Select(Function(x) x.Value)
Public Function FirstNumberIndex(ByVal value As String) As Integer
Dim index = 0
Dim found = value.Length
Do While index < value.Length
If Char.IsDigit(value.Chars(index)) Then
found = index
Exit Do
End If
index += 1
Loop
Return found
End Function
Private Sub Form1_SizeChanged(sender As System.Object, e As System.EventArgs) Handles MyBase.SizeChanged
hH = PictureHolder.Height
hW = PictureHolder.Width
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.Icon = My.Resources.PhotoIcon
If My.Application.CommandLineArgs.Count = 1 Then
Try
img = Image.FromFile(My.Application.CommandLineArgs(0))
iH = img.Height
iW = img.Width
hH = PictureHolder.Height
hW = PictureHolder.Width
If iH > hH - 5 Or iW > hW - 5 Then
zoomBar.Value = Math.Round((hH - 5) / iH * 100, 0)
Picture.Height = iH * (zoomBar.Value / 100)
Picture.Width = iW * (zoomBar.Value / 100)
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
Else
Picture.Height = iH
Picture.Width = iW
Picture.Top = (hH - 5) / 2 - Picture.Height / 2
Picture.Left = (hW - 5) / 2 - Picture.Width / 2
End If
Picture.Image = img
fileName.Text = My.Application.CommandLineArgs(0)
loc = My.Application.CommandLineArgs(0).Remove(My.Application.CommandLineArgs(0).LastIndexOf("\"))
For Each file As String In FileIO.FileSystem.GetFiles(loc)
If Regex.Matches(file, picPattern, RegexOptions.IgnoreCase).Count > 0 Then
files.Add(file)
End If
If file = My.Application.CommandLineArgs(0) Then
fileIndex = files.IndexOf(file)
End If
Next
Catch ex As Exception
MsgBox("ERROR: " & ex.Message, MsgBoxStyle.OkOnly, "ERROR")
Clipboard.SetText(ex.Message)
End Try
End If
fWinState = Me.WindowState
End Sub
Private Sub zoomBar_ValueChanged(sender As System.Object, e As System.EventArgs) Handles zoomBar.ValueChanged
Picture.Height = iH * (zoomBar.Value / 100)
Picture.Width = iW * (zoomBar.Value / 100)
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
End Sub
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
If Not (fWinState = Me.WindowState) Then
hH = PictureHolder.Height
hW = PictureHolder.Width
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
fWinState = Me.WindowState
End If
End Sub
Private Sub Picture_MouseMove(sender As System.Object, e As MouseEventArgs) Handles Picture.MouseMove
If Picture.Width > PictureHolder.Width Or Picture.Height > PictureHolder.Height Then
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim DeltaX As Integer = (m_Coordnates.X - e.X)
Dim DeltaY As Integer = (m_Coordnates.Y - e.Y)
PictureHolder.AutoScrollPosition = New Drawing.Point((DeltaX - PictureHolder.AutoScrollPosition.X), (DeltaY - PictureHolder.AutoScrollPosition.Y))
Else
Dim curStream As New System.IO.MemoryStream(My.Resources.oCur)
Picture.Cursor = New Cursor(curStream)
End If
Else
Picture.Cursor = Cursors.Default
End If
End Sub
Private Sub Picture_MouseDown(sender As System.Object, e As MouseEventArgs) Handles Picture.MouseDown
If Picture.Width > PictureHolder.Width Or Picture.Height > PictureHolder.Height Then
m_Coordnates = New Point(e.X, e.Y)
Dim curStream As New System.IO.MemoryStream(My.Resources.cCur)
Picture.Cursor = New Cursor(curStream)
End If
End Sub
Private Sub open_Click(sender As System.Object, e As System.EventArgs) Handles openFile.Click
If fileOpener.ShowDialog = Windows.Forms.DialogResult.OK Then
Try
img = Image.FromFile(fileOpener.FileName)
iH = img.Height
iW = img.Width
hH = PictureHolder.Height
hW = PictureHolder.Width
If iH > hH Or iW > hW Then
zoomBar.Value = Math.Round((hH - 5) / iH * 100, 0)
Picture.Height = iH * (zoomBar.Value / 100)
Picture.Width = iW * (zoomBar.Value / 100)
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
Else
Picture.Height = iH
Picture.Width = iW
Picture.Top = (hH - 5) / 2 - Picture.Height / 2
Picture.Left = (hW - 5) / 2 - Picture.Width / 2
End If
Picture.Image = img
fileName.Text = fileOpener.FileName
loc = fileOpener.FileName.Remove(fileOpener.FileName.LastIndexOf("\"))
For Each file As String In FileIO.FileSystem.GetFiles(loc)
If Regex.Matches(file, picPattern, RegexOptions.IgnoreCase).Count > 0 Then
files.Add(file)
End If
Next
files.Sort(sorter)
For Each file As String In files
If file = fileOpener.FileName Then
fileIndex = files.IndexOf(file)
Exit For
End If
Next
Catch ex As Exception
MsgBox("ERROR: " & ex.Message & vbNewLine & vbNewLine & ex.StackTrace, MsgBoxStyle.OkOnly, "ERROR")
Clipboard.SetText(ex.Message)
End Try
End If
End Sub
Private Sub previousFile_Click(sender As System.Object, e As System.EventArgs) Handles previousFile.Click
If fileIndex <> 0 Then
fileIndex -= 1
Else
fileIndex = files.Count - 1
End If
Try
img = Image.FromFile(files(fileIndex))
iH = img.Height
iW = img.Width
hH = PictureHolder.Height
hW = PictureHolder.Width
If iH > hH Or iW > hW Then
zoomBar.Value = Math.Round((hH - 5) / iH * 100, 0)
Picture.Height = iH * (zoomBar.Value / 100)
Picture.Width = iW * (zoomBar.Value / 100)
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
Else
Picture.Height = iH
Picture.Width = iW
Picture.Top = (hH - 5) / 2 - Picture.Height / 2
Picture.Left = (hW - 5) / 2 - Picture.Width / 2
End If
Picture.Image = img
fileName.Text = files(fileIndex)
loc = files(fileIndex).Remove(files(fileIndex).LastIndexOf("\"))
Catch ex As Exception
MsgBox("ERROR: " & ex.Message, MsgBoxStyle.OkOnly, "ERROR")
Clipboard.SetText(ex.Message)
End Try
End Sub
Private Sub nextFile_Click(sender As System.Object, e As System.EventArgs) Handles nextFile.Click
If fileIndex <> files.Count - 1 Then
fileIndex += 1
Else
fileIndex = 0
End If
Try
img = Image.FromFile(files(fileIndex))
iH = img.Height
iW = img.Width
hH = PictureHolder.Height
hW = PictureHolder.Width
If iH > hH Or iW > hW Then
zoomBar.Value = Math.Round((hH - 5) / iH * 100, 0)
Picture.Height = iH * (zoomBar.Value / 100)
Picture.Width = iW * (zoomBar.Value / 100)
If Picture.Height < hH Then
Picture.Top = PictureHolder.Height / 2 - Picture.Height / 2
Else
Picture.Top = 0
End If
If Picture.Width < hW Then
Picture.Left = PictureHolder.Width / 2 - Picture.Width / 2
Else
Picture.Left = 0
End If
Else
Picture.Height = iH
Picture.Width = iW
Picture.Top = (hH - 5) / 2 - Picture.Height / 2
Picture.Left = (hW - 5) / 2 - Picture.Width / 2
End If
Picture.Image = img
fileName.Text = files(fileIndex)
loc = files(fileIndex).Remove(files(fileIndex).LastIndexOf("\"))
Catch ex As Exception
MsgBox("ERROR: " & ex.Message, MsgBoxStyle.OkOnly, "ERROR")
Clipboard.SetText(ex.Message)
End Try
End Sub
Private Sub copyFile_Click(sender As System.Object, e As System.EventArgs) Handles copyFile.Click
End Sub
Private Sub moveFile_Click(sender As System.Object, e As System.EventArgs) Handles moveFile.Click
End Sub
End Class
Class AlphanumericSortedList
Inherits List(Of String)
Implements IComparer(Of String)
Public Function Compare(X As String, Y As String) As Integer Implements IComparer(Of String).Compare
Dim C, I, J, IX, IY As Integer
For I = 0 To X.Length - 1
Dim S As String = X.Substring(I)
If Integer.TryParse(X.Substring(I), IX) Then Exit For
Next
For J = 0 To Y.Length - 1
Dim S As String = Y.Substring(J)
If Integer.TryParse(Y.Substring(J), IY) Then Exit For
Next
C = String.Compare(X.Substring(0, I), Y.Substring(0, J))
If C = 0 Then C = If(IX < IY, -1, If(IX = IY, 0, 1))
Return C
End Function
End Class
Before sort a a1 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a2 a20
After sort a a1 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a2 a20
I'm sorry if I misspelled something or my grammar is wrong, I've never done well in those subjects.
Friday, April 27, 2012 9:22 PM
"it didn't work for me"
Did you try the code I posted? It's a stand alone application. You would have to understand it to copy and paste random lines of it into another application.