列表(字符串)不使用 IComparer 进行数字排序

问题描述 投票:0回答:1

我有一个以这种方式排序的字符串列表。我希望它们正常排序。我已经实现了 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

不太确定哪里出了问题。我觉得这在某些时候起作用了。对此的任何帮助都会有所帮助。我刚刚学习这些东西,所以如果你能提供更多细节,那将会很有帮助。

vb.net
1个回答
0
投票

嗯...你的代码几乎是完美的。

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

© www.soinside.com 2019 - 2024. All rights reserved.