假设我们有以下字符串:
string data= "/temp string";
如果我们想要删除第一个字符/
,可以通过很多方式来实现,例如:
data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);
但是,实际上我不知道哪个算法最好并且执行速度更快..
有一个算法是最好的还是所有算法都一样?
假设我们有以下字符串:
string data= "/temp string";
如果我们想要删除第一个字符/
,可以通过很多方式来实现,例如:
data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);
但是,实际上我不知道哪个算法最好并且执行速度更快..
有一个算法是最好的还是所有算法都一样?
第二个选项与其他选项真的不同 - 如果字符串是“///foo”,它将变为“foo”,而不是“//foo”。
与第三个选项相比,第一个选项需要更多的工作才能理解 - 我认为Substring
选项最常见和易读。
(显然,每个选项作为单独语句都不会有任何有用的效果 - 您需要将结果赋给变量,可能是data
本身。)
我不会考虑性能,除非它实际上对您造成了问题 - 在这种情况下,唯一知道的方法就是拥有测试用例,然后很容易为每个选项运行这些测试用例并比较结果。我期望Substring
在这里可能是最快的,因为Substring
总是从原始输入的单个块中创建字符串,而Remove
则必须至少可能地将起始块和结束块粘合在一起。
我知道这是超级优化的领域,但这似乎是一个很好的理由来测试一下 BenchmarkDotNet
。在这个测试中(甚至在.NET Core上),Substring
比 Remove
略微快一些,在这个样本测试中:19.37ns 对比 Remove
的 22.52ns。所以大约快了16%。
using System;
using BenchmarkDotNet.Attributes;
namespace BenchmarkFun
{
public class StringSubstringVsRemove
{
public readonly string SampleString = " My name is Daffy Duck.";
[Benchmark]
public string StringSubstring() => SampleString.Substring(1);
[Benchmark]
public string StringRemove() => SampleString.Remove(0, 1);
public void AssertTestIsValid()
{
string subsRes = StringSubstring();
string remvRes = StringRemove();
if (subsRes == null
|| subsRes.Length != SampleString.Length - 1
|| subsRes != remvRes) {
throw new Exception("INVALID TEST!");
}
}
}
class Program
{
static void Main()
{
// let's make sure test results are really equal / valid
new StringSubstringVsRemove().AssertTestIsValid();
var summary = BenchmarkRunner.Run<StringSubstringVsRemove>();
}
}
}
结果:
BenchmarkDotNet=v0.11.4, OS=Windows 10.0.17763.253 (1809/October2018Update/Redstone5)
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview-010184
[Host] : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT
DefaultJob : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT
| Method | Mean | Error | StdDev |
|---------------- |---------:|----------:|----------:|
| StringSubstring | 19.37 ns | 0.3940 ns | 0.3493 ns |
| StringRemove | 22.52 ns | 0.4062 ns | 0.3601 ns |
data = data[1..];
我猜Remove
和Substring
可能并列第一,因为它们都会截取字符串的一个固定长度,而TrimStart
则需要从左到右逐个检查每个字符,然后再执行与前两种方法完全相同的操作。不过,这已经是深入探讨了。
Substring
和Remove
都依赖于一个私有方法FillSubstring
。 - Marcelo Cantosstring Remove(this string source, int from, int to) { return source.SubString(0, from) + source.SubString(to); }
- DykamSystem.PInvoke.EE.AllocateString
жқҘеҲҶй…Қзӣ®ж Үеӯ—з¬ҰдёІеҜ№иұЎпјҢ然еҗҺи°ғз”ЁFillSubstring
жқҘеӨҚеҲ¶еӯ—з¬ҰгҖӮжҲ‘жҳҜеңЁзңӢй”ҷдәҶеҗ—пјҹ - Marcelo CantosSubstring
> Remove
)。我不会再发表评论了,因为这个讨论已经占用了我足够的时间。 - Jaroslav Jandek如果您真的关心,可以对其进行性能分析。编写多次迭代的循环并观察发生的情况。但很有可能这不是您应用程序中的瓶颈,TrimStart似乎是最符合语义的选项。在优化之前,努力编写可读的代码。
TrimStart
不会删除第一个字符,它会从开头删除n
个字符。Substring
是最快的。 - Jaroslav JandekTrimStart()
完全行不通。 - BoltClock