有条件剥离字符串右侧部分的最快方法

时间:2018-11-06 16:19:43

标签: string vb.net split

我需要删除字符串末尾的数字部分。以下是一些示例:

  • "abcd1234"-> "abcd"
  • "a3bc45"-> "a3bc"
  • "kj3ih5"-> "kj3ih"

您明白了。

我实现了一个可以很好地实现此目的的功能。

Function VarStamm(name As String) As String
    Dim i, a As Integer
    a = 0
    For i = Len(name) To 1 Step -1
        If IsNumeric(Mid(name, i, 1)) = False Then
            i = i + 1
            Exit For
        End If
    Next i
    If i <= Len(name) Then
        VarStamm = name.Substring(0, i - 1)
    Else
        VarStamm = name
    End If
End Function

问题是:是否有任何 更快 (速度更高效)的方法?问题是,我在一个具有300万次迭代的循环中调用此函数,希望它能更有效。

我了解String.LastIndexOf方法,但是当我需要字符串中最后一个连接数字的索引时,我不知道如何使用它。

3 个答案:

答案 0 :(得分:3)

您可以先使用Array.FindLastIndex,然后再使用Substring

Dim lastNonDigitIndex = Array.FindLastIndex(text.ToCharArray(), Function(c) Not char.IsDigit(c))

If lastNonDigitIndex >= 0
    lastNonDigitIndex += 1
    Dim part1 = text.Substring(0, lastNonDigitIndex)
    Dim part2 = text.Substring(lastNonDigitIndex)
End If 

答案 1 :(得分:2)

鉴于您的函数VarStamm和Tim Schmelter的函数VarStamm2,这是我编写的一个小测试性能。我键入了一个任意的长字符串,该字符串的右部很大,并运行了100万次。

Module StackOverlow

    Sub Main()
        Dim testStr = "azekzoerjezoriezltjreoitueriou7657678678797897898997897978897898797989797"

        Console.WriteLine("RunTime :" + vbNewLine +
               " - VarStamm : " + getTimeSpent(AddressOf VarStamm, testStr) + vbNewLine +
               " - VarStamm2 : " + getTimeSpent(AddressOf VarStamm2, testStr))

    End Sub

    Function getTimeSpent(f As Action(Of String), str As String) As String
        Dim sw As Stopwatch = New Stopwatch()
        Dim ts As TimeSpan

        sw.Start()
        For i = 1 To 1000000
            f(str)
        Next
        sw.Stop()
        ts = sw.Elapsed
        Return String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds,
            ts.Milliseconds / 10)
    End Function

    Function VarStamm(name As String) As String
        Dim i, a As Integer
        a = 0
        For i = Len(name) To 1 Step -1
            If IsNumeric(Mid(name, i, 1)) = False Then
                i = i + 1
                Exit For
            End If
        Next i
        If i <= Len(name) Then
            VarStamm = name.Substring(0, i - 1)
        Else
            VarStamm = name
        End If
    End Function

    Function VarStamm2(name As String) As String
        Dim lastNonDigitIndex = Array.FindLastIndex(name.ToCharArray(), Function(c) Not Char.IsDigit(c))

        If lastNonDigitIndex >= 0 Then
            lastNonDigitIndex += 1
            Return name.Substring(0, lastNonDigitIndex)
        End If
        Return name
    End Function
End Module

这是我得到的输出:

RunTime :
 - VarStamm : 00:00:38.33
 - VarStamm2 : 00:00:02.72

是的,您应该选择他的答案,他的代码既漂亮又高效。

答案 2 :(得分:2)

我对Array.FindLastIndex方法实际上更快表示怀疑,因此我自己进行了测试。我借用了Amessihel发布的测试代码,但添加了第三种方法:

Function VarStamm3(name As String) As String
    Dim i As Integer
    For i = name.Length - 1 To 0 Step -1
        If Not Char.IsDigit(name(i)) Then
            Exit For
        End If
    Next i
    Return name.Substring(0, i + 1)
End Function

它使用您的原始算法,但只是将旧的VB6样式的字符串方法替换为较新的.NET等效方法。这是我机器上的结果:

RunTime :
 - VarStamm : 00:00:07.92
 - VarStamm2 : 00:00:00.60
 - VarStamm3 : 00:00:00.23

如您所见,您的原始算法已经进行了很好的调整。问题不是循环。问题是MidIsNumericLen。由于Tim的方法不使用这些方法,因此速度更快。但是,如果您坚持使用手动for循环,那么在所有条件都相同的情况下,它的速度是使用Array.FindLastIndex的两倍