我有一个以这种方式排序的字符串列表。我希望它们正常排序。我已经实现了 IComparer,但它不起作用。
Slide1.jpg
Slide10.jpg
Slide11.jpg
Slide12.jpg
Slide2.jpg
Slide3.jpg
我正在使用这样的比较器
Dim files = Directory.GetFiles("c:\PowerPoint\Images", "*.jpg", SearchOption.AllDirectories).ToList()
files.Sort(New NaturalComparer(True))
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+) Then", 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
不太确定哪里出了问题。我觉得这在某些时候起作用了。对此的任何帮助都会有所帮助。我刚刚学习这些东西,所以如果你能提供更多细节,那将会很有帮助。
嗯...你的代码几乎是完美的。
Compare
函数只需要进行一些小的改进。
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 Integer.TryParse(x, Nothing) AndAlso Not Integer.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 Integer.TryParse(x, Nothing) AndAlso Not Integer.TryParse(right(_pos), Nothing) Then
Return -1 * _order
ElseIf Not Integer.TryParse(x, Nothing) AndAlso Integer.TryParse(right(_pos), Nothing) Then
Return 1 * _order
Else
Dim result = Decimal.Compare(Integer.Parse(x), Integer.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
我用下面的代码测试了它:
Dim slides As List(Of String) = New List(Of String) From {"Slide1.jpg", "Slide10.jpg", "Slide11.jpg", "Slide12.jpg", "Slide2.jpg", "Picture3.jpg"}
slides.Sort(New NaturalComparer(True))
结果:
图片3.jpg
幻灯片1.jpg
幻灯片2.jpg
幻灯片10.jpg
幻灯片11.jpg
幻灯片12.jpg