String 有条件地剥离字符串右侧部分的最快方法
我需要删除字符串末尾的数字部分。以下是一些例子: abcd1234->abcd a3bc45->a3bc kj3ih5->kj3ih 你明白了 我实现了一个函数,该函数为此目的运行良好String 有条件地剥离字符串右侧部分的最快方法,string,vb.net,split,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)) = Fals
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方法,但当我需要字符串中最后一个连接的数字的索引时,我不知道如何使用它。您可以使用Array.FindLastIndex,然后使用Substring:
您可以使用Array.findlastinex,然后使用子字符串:
考虑到您的函数VarStamm和timschmelter的一个名为VarStamm2的函数,下面是我编写的一个小型性能测试。我输入了一个任意的长字符串,右边有一个巨大的部分,并运行了一百万次函数
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
是的,你应该选择他的答案,他的代码既漂亮又高效。考虑到你的函数VarStamm和Tim Schmelter的函数VarStamm2,下面是我编写的一个小测试性能。我输入了一个任意的长字符串,右边有一个巨大的部分,并运行了一百万次函数
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
是的,你应该选择他的答案,他的代码既漂亮又高效。我怀疑Array.findlastedex方法实际上更快,所以我自己测试了它。我借用了Amessichel发布的测试代码,但添加了第三种方法:
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
正如您所看到的,您的原始算法已经进行了很好的调整。问题不在于循环。问题是Mid、IsNumeric和Len。因为蒂姆的方法没有使用这些,所以速度要快得多。但是,如果你坚持使用手动for循环,它的速度是使用Array.findlastedex的两倍,在所有条件相同的情况下我怀疑Array.findlastedex方法实际上更快,所以我自己测试了它。我借用了Amessichel发布的测试代码,但添加了第三种方法:
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
正如您所看到的,您的原始算法已经进行了很好的调整。问题不在于循环。问题是Mid、IsNumeric和Len。因为蒂姆的方法没有使用这些,所以速度要快得多。但是,如果您坚持使用手动for循环,它的速度是使用Array.findlastedex的两倍,在所有条件相同的情况下该函数只返回左边的部分,但这对我来说是可以的,这对我来说似乎非常有效。您可以创建自己的方法,该方法比IsNumeric更有效。通过数组语法(如namei)获取当前字符可能更快。但除了这些小事情,通用算法看起来不错。我最大的抱怨是您使用了传统的VB6风格的函数,如Mid、IsNumeric和Len,而不是更新的.NET等效函数,但我不知道.NET等效函数是否真的会更快。看起来不错,除非你需要处理字符串结尾不是数字的情况,你仍然需要拆分它。函数只返回左边的部分,但这对我来说没关系,看起来对我来说效率很高。您可以创建自己的方法,该方法比IsNumeric更有效。通过数组语法(如namei)获取当前字符可能更快。但除了这些小事情,通用算法看起来不错。我最大的抱怨是您使用了传统的VB6风格的函数,如Mid、IsNumeric和Len,而不是更新的.NET等效函数,但我不知道.NET等效函数是否真的会更快。看起来不错,除非你需要处理字符串结尾不是数字的情况,你仍然需要拆分它。@Amesshiel:比什么慢,为什么?@Amesshiel:你测试了这两个,或者为什么你说它慢?最慢的部分是text.tochararrymy bad,你的代码要快得多。我会发布一个答案来证明这一点。@Amesshiel:如果您想要更快的版本,您需要为String.FindLastIndex创建一个扩展方法,该扩展方法将谓词作为Char、Boolean的FuncOf。然后,您可以向后循环字符串,而无需使用ToCharray,因为ToCharray总是创建一个新字符。这个方法的主体是:For i As Int32=text.Length-1到0步骤-1如果谓词texti那么返回i Next Return-1非常感谢你们!巨大的成功:@Amesshiel:比什么慢?为什么?@Amesshiel:你测试了两者还是说慢?最慢的部分是text.tochararrymy bad,你的代码要快得多。我会发布一个答案来证明这一点。@Amesshiel:如果你想要一个更快的版本,你可以
需要为String.FindLastIndex创建一个扩展方法,该扩展方法将谓词作为Char、Boolean的函数。然后,您可以向后循环字符串,而无需使用ToCharray,因为ToCharray总是创建一个新字符。这个方法的主体是:For i As Int32=text.Length-1到0步骤-1如果谓词texti那么返回i Next Return-1非常感谢你们!巨大的成功:你的怀疑并非完全错误。看我的答案。你的怀疑并不是完全错误的。看我的答案。是的,确实值得一提的是,这个问题与算法无关。听起来您的实现是第一位的。@SteveDoggart计时时,您是否从Tim的解决方案中删除了Dim part2=text.SubstringlastNonDigitIndex?“我不喜欢长的一行,我对速度差感兴趣,如果有的话。”玛丽问得好。我刚刚从Amesshiel的答案中复制了代码,并添加了新方法。看起来,在VarStamm2方法中,他删除了不必要的行,所以这就是我测试的内容。谢谢你,Steve。是的,确实值得一提的是,这个问题与算法无关。听起来您的实现是第一位的。@SteveDoggart计时时,您是否从Tim的解决方案中删除了Dim part2=text.SubstringlastNonDigitIndex?“我不喜欢长的一行,我对速度差感兴趣,如果有的话。”玛丽问得好。我刚刚从Amesshiel的答案中复制了代码,并添加了新方法。看起来,在VarStamm2方法中,他删除了不必要的行,所以这就是我测试的内容。谢谢你,Steve。