删除String中第一个char的最快方法

Amr*_*awy 186 c# string performance substring trim

假设我们有以下字符串

string data= "/temp string";
Run Code Online (Sandbox Code Playgroud)

如果我们想删除第一个字符,/我们可以通过很多方式来完成,例如:

data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);
Run Code Online (Sandbox Code Playgroud)

但是,我真的不知道哪一个拥有最好的算法并且做得更快..
有一个是最好的还是全部都是一样的?

Jon*_*eet 135

第二个选项实际上与其他选项不同 - 如果字符串是"/// foo",它将变为"foo"而不是"// foo".

第一个选项比第三个选项需要更多的工作来理解 - 我会将Substring选项视为最常见和可读的选项.

(显然,每个作为单独的语句都不会做任何有用的事情 - 你需要将结果分配给变量,可能是data自己.)

我不会在这里考虑性能,除非它实际上成为你的问题 - 在这种情况下,你知道的唯一方法是拥有测试用例,然后很容易为每个选项运行这些测试用例比较结果.我希望Substring这里可能是最快的,因为Substring总是最终从原始输入的一个块创建一个字符串,而Remove至少可能将起始块和结束块粘合在一起.

  • 我现在通过调用每个约90000000来检查并且我得到以下结果:删除:06.63 - TrimStart:04.71 - subString:03.09所以从结果子串是最好的 (32认同)
  • 请记住,当您以这种方式测试性能时,您会受到CPU缓存的影响,因此您需要在随机字符串上执行此操作,预先填充数组(列表),并随机选择该数组的元素(列表). (4认同)

Vas*_*vos 22

.Net Core中这也有效:

data = data[1..];
Run Code Online (Sandbox Code Playgroud)


Mar*_*tos 9

我猜想,Remove并且Substring将并列第一,因为他们都啜了绳子的固定大小的部分,而TrimStart不会从左边上的每个字符的测试扫描,然后必须执行完全相同的工作为另外两种方法.但说真的,这是分裂的头发.


Nic*_*sen 7

我知道这是过度优化的领域,但这似乎是一个很好的借口BenchmarkDotNet。该测试的结果(甚至在.NET Core上)也SubstringRemove本示例测试中的结果稍快:19.37ns vs .22ns Remove。所以快约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>();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

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 |
Run Code Online (Sandbox Code Playgroud)


Ste*_*all 6

如果你真的关心的话,你可以描述它.编写一个循环的多次迭代,看看会发生什么.但是,这可能不是您应用程序中的瓶颈,TrimStart似乎在语义上最正确.努力在优化之前可读地编写代码.

  • `TrimStart`是最不正确的,因为``// temp string'.TrimStart('/')`将*不*只删除第一个''/'`. (6认同)