【问题标题】:Natural-sort Strings which are in a List(of class)列表中的自然排序字符串(类)
【发布时间】:2022-01-08 13:33:56
【问题描述】:

很遗憾,我的代码有问题。在过去的几个月里,我不时地在我的程序中添加了一些东西。现在代码有点“错误构建(t)”,我需要你的帮助。 我有一个程序,其中有线程和帖子——就像在一个经典的互联网论坛中一样。一个线程可以包含多个帖子;一个帖子包含多个图像和文本。所以... 您可以单击 ListBox 中的某个帖子并尽可能大地显示其图像。这是通过单独的表格完成的。使用 3 个不同的单选按钮,我可以根据图像的大小(百万像素)、修改日期或文件名对其进行排序。为了能够按百万像素排序,我曾经创建了一个类Bildeigenschaften(图像属性类)。因此sorted_ListList(of Bildeigenschaften)。 今天,我发现按名称排序与在 Windows 资源管理器中按名称排序不同。 Windows 资源管理器排序自然(我发现),所以它是这样的

ABC9

ABC10

而不是像我的程序中那样

ABC10

ABC9

。 所以我得到了一些排序“自然”的代码。我现在如何获得这个链接?

表格

Private Property List_of_class_Bildeigenschaften As New List(Of Bildeigenschaften)
   
    Private sorted_List As List(Of Bildeigenschaften)
'--------------------
Private Sub RadioButton2_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton2.CheckedChanged
        If RadioButton2.Checked Then
            sorted_List = List_of_class_Bildeigenschaften.OrderBy(Function(o) o._FileInfo.Name).ToList()
            If CheckBox1.Checked Then
                sorted_List.Reverse()
            End If
        End If

        If CheckBox1.Checked Then
            sorted_List.Reverse()
        End If
    End Sub
'--------------------
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 As Integer = 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

Bildeigenschaften 类

Public NotInheritable Class Bildeigenschaften
    Public Megapixels As UInt32
    Public Bild As System.Drawing.Bitmap
    Public _FileInfo As IO.FileInfo

    Public Sub New(ByVal Breite As UInt32, ByVal Hoehe As UInt32, ByVal Bild As Bitmap, ByVal einefileinfo As IO.FileInfo)
        Me.Megapixels = Breite * Hoehe
        Me.Bild = Bild
        Me._FileInfo = einefileinfo
    End Sub
End Class

因此,我的问题与this不相似。

【问题讨论】:

  • 这能回答你的问题吗? Natural Sort Order in C#
  • @GSerg 这是我发现的许多东西之一。但我有一个(类)列表,我不能只写sorted_List.Sort (new NaturalComparer)。你明白我的意思吗?
  • 然后让你的NaturalComparerImplements IComparer(Of Class),并查看Compare()中的相应属性。

标签: vb.net sorting


【解决方案1】:

您可以使用资源管理器也使用的 Windows 的 StrCmpLogicalW

Public Class NaturalSortComparer
    Implements IComparer(Of String)

    Declare Unicode Function StrCmpLogicalW Lib "shlwapi.dll" ( _
        ByVal s1 As String, _
        ByVal s2 As String) As Int32

    Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements System.Collections.Generic.IComparer(Of String).Compare
        Return StrCmpLogicalW(x, y)
    End Function

End Class

例如:

Dim list = New List(Of String)
list.Add("ABC10")
list.Add("ABC9")
Console.WriteLine(String.Join(",", list))
list.Sort(New NaturalSortComparer())
Console.WriteLine(String.Join(",", list))

输出:

ABC10,ABC9
ABC9,ABC10

您也可以将它与 LINQ 一起使用:

list = list.OrderBy(Function(s) s, New NaturalSortComparer()).ToList()

这也回答了您如何在查询中安装比较器的问题:

sorted_List = List_of_class_Bildeigenschaften.OrderBy(Function(o) o._FileInfo.Name, New NaturalComparer()).ToList()

【讨论】:

  • @AndrewMorton:是的,我刚刚编辑了我的答案以表明,最后一种方法
  • 蒂姆和@AndrewMorton 非常感谢!那行得通。我很感激。 sorted_List = List_of_class_Bildeigenschaften.OrderBy(Function(o) o._FileInfo.Name, New NaturalSortComparer()).ToList()
猜你喜欢
  • 1970-01-01
  • 2014-04-11
  • 1970-01-01
  • 2011-02-17
  • 2021-08-30
  • 2021-07-10
相关资源
最近更新 更多