【问题标题】:How to order an arraylist by versions or dot delimited in VB.NET [duplicate]如何在VB.NET中按版本或点分隔排列数组列表[重复]
【发布时间】:2021-02-03 07:49:39
【问题描述】:

我的数组列表中有这种输入:

1
1.1
1.1.1
1.1.1.1
1.1.2
1.10
1.11
1.2
1.9

我想对其进行排序,得到如下所示的结果:

1
1.1
1.1.1
1.1.1.1
1.1.2
1.2
1.9    
1.10
1.11

我找到了其他语言的可能解决方案,但我很难理解它们。 我有这个函数可以读取没有扩展名的文件夹的文件名,但我不知道如何排序(我试图将它们视为小数,但它不起作用)。

    Function GetVersions(ByVal mypath As String) As ArrayList
    Dim Versions As New ArrayList

    For Each Ver As String In My.Computer.FileSystem.GetFiles(mypath)
        If IsNumeric(Path.GetFileNameWithoutExtension(Ver)) Then
            Versions.Add(Decimal.Parse(Path.GetFileNameWithoutExtension(Ver)).ToString("#0.00")) 
        End If
    Next

    Dim mesg As String = ""
    For Each str As String In Versions
        mesg = mesg & str & vbCrLf
    Next
    MsgBox(mesg)

    Return Versions
    End Function

我对 IComparer 不是很熟悉,但如果需要,我可以实现它

【问题讨论】:

  • 我认为你会想要实现IComparer,并在比较函数中,用'.'分隔。字符(即"."c),将片段解析为整数,然后从那里继续。如果您知道所有内容都将采用该格式,那么它并不是特别复杂。鉴于您声明的版本格式(多个 '.' 分隔符),您在解析为 Decimal 时显示的代码没有任何意义。
  • 顺便说一句,除非您有充分的理由这样做(与旧版组件兼容,或者这是旧版组件),否则我建议您更喜欢 List(Of String) 而不是 ArrayList
  • 可能有多少个周期?每个位置的数字范围是多少?
  • @dbasnett 我认为有 4 个句点,每个位置的数字范围是什么意思
  • @Craig 你有任何代码示例来说明你告诉我的内容吗?

标签: vb.net sorting arraylist version icomparer


【解决方案1】:

示例中的类将版本号存储为编码的 Long,每个位置都在 0 到 255 之间,8 位。除非你有很多这样的东西,否则可能有点矫枉过正......;)

需要一个带有按钮的表单,

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Test of Class VersionNumber
        Dim l As New List(Of VersionNumber)

        Dim test As XElement = <t>
                                   <t>1.11</t>
                                   <t>1</t>
                                   <t>1.2</t>
                                   <t>1.2.3</t>
                                   <t>1.2.3.4</t>
                                   <t>1.1.3</t>
                                   <t>1.1.2</t>
                                   <t>1.10</t>
                                   <t>1.2.1</t>
                                   <t>1.2</t>
                                   <t>1.9</t>
                                   <t>1.2.3.4.5.6.7.8</t>
                               </t>

        Debug.WriteLine("")
        Debug.WriteLine("")
        Dim foo As VersionNumber
        For Each el As XElement In test.Elements
            Debug.WriteLine(el.Value)
            foo = New VersionNumber(el.Value)
            l.Add(foo)
        Next
        l.Sort()

        Debug.WriteLine("")
        Debug.WriteLine("Sorted")
        For Each vn As VersionNumber In l
            Debug.WriteLine(vn.ToString)
        Next
    End Sub
End Class

Public Class VersionNumber
    Implements IComparable(Of VersionNumber), IEquatable(Of VersionNumber)

    Protected Friend _version As Long = 0L
    Private _verstring As String

    Public Sub New(Version As String)
        Dim prts() As String = Version.Trim.Split("."c)
        If prts.Length <= 0 OrElse prts.Length > 8 Then
            Throw New ArgumentException("Invalid version")
        Else
            Dim idx As Integer = 0
            Dim shft As Integer = 8 - (8 - (8 - prts.Length))
            Do While shft < 8
                Dim L As Long = 0L
                If Long.TryParse(prts(idx), L) AndAlso L >= 0 AndAlso L < 256L Then
                    shft += 1
                    idx += 1
                    Me._version = Me._version Or L
                    If shft <> 8 Then Me._version = Me._version << 8
                Else
                    Throw New ArgumentException("Invalid version")
                End If
            Loop
            Me._verstring = Version.Trim
            shft = (8 - (8 - (8 - prts.Length))) * 8
            Me._version = Me._version << shft
        End If
    End Sub

    Public Overrides Function ToString() As String
        Return Me._verstring
    End Function

#Region " and Ops"
    Public Function CompareTo(other As VersionNumber) As Integer _
                Implements IComparable(Of VersionNumber).CompareTo
        'https://msdn.microsoft.com/en-us/library/system.icomparable.compareto(v=vs.110).aspx
        'return values and their meaning:
        ' Less than zero      This instance precedes other in the sort order. 
        ' Zero                This instance occurs in the same position in the sort order as other. 
        ' Greater than zero   This instance follows other in the sort order. 

        If other Is Nothing Then
            Return 1 'By definition, any object compares greater than (or follows) null, and two null references compare equal to each other
        ElseIf Me = other Then
            Return 0
        ElseIf Me < other Then
            Return -1
        Else
            Return 1
        End If
    End Function

    Public Overloads Function Equals(other As VersionNumber) As Boolean _
                Implements IEquatable(Of VersionNumber).Equals

        Select Case Me.CompareTo(other)
            Case 0
                Return True
            Case Else
                Return False
        End Select
    End Function

    Public Shared Operator =(VersNum1 As VersionNumber,
                             VersNum2 As VersionNumber) As Boolean
        Return VersNum1._version.Equals(VersNum2._version)
    End Operator

    Public Shared Operator <>(VersNum1 As VersionNumber, VersNum2 As VersionNumber) As Boolean
        Return Not VersNum1._version.Equals(VersNum2._version)
    End Operator

    Public Shared Operator >(VersNum1 As VersionNumber, VersNum2 As VersionNumber) As Boolean
        Return VersNum1._version > VersNum2._version
    End Operator

    Public Shared Operator <(VersNum1 As VersionNumber, VersNum2 As VersionNumber) As Boolean
        Return VersNum1._version < VersNum2._version
    End Operator

    Public Shared Operator >=(VersNum1 As VersionNumber, VersNum2 As VersionNumber) As Boolean
        Return VersNum1 > VersNum2 OrElse VersNum1.Equals(VersNum2)
    End Operator

    Public Shared Operator <=(VersNum1 As VersionNumber, VersNum2 As VersionNumber) As Boolean
        Return VersNum1 < VersNum2 OrElse VersNum1.Equals(VersNum2)
    End Operator
#End Region

End Class

【讨论】:

  • 谢谢,我没想到排序会这么复杂:/ 我还在努力理解
  • @Rchrd - 它看起来很复杂,因为版本被压缩成 Long 的方式,如果你从未见过 IComparer 实现。要查看 IComparer 的实际运行情况,请在 .Sort 上休息一下,然后逐步进行多次迭代。
猜你喜欢
  • 2017-06-08
  • 1970-01-01
  • 2015-09-14
  • 2021-10-24
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多