Fastest way to remove first char in a String

C#StringSubstringPerformanceTrim

C# Problem Overview


Say we have the following string

string data= "/temp string";

If we want to remove the first character / we can do by a lot of ways such as :

data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);

But, really I don't know which one has the best algorithm and doing that faster..
Is there a one that is the best or all are the same ?

C# Solutions


Solution 1 - C#

The second option really isn't the same as the others - if the string is "///foo" it will become "foo" instead of "//foo".

The first option needs a bit more work to understand than the third - I would view the Substring option as the most common and readable.

(Obviously each of them as an individual statement won't do anything useful - you'll need to assign the result to a variable, possibly data itself.)

I wouldn't take performance into consideration here unless it was actually becoming a problem for you - in which case the only way you'd know would be to have test cases, and then it's easy to just run those test cases for each option and compare the results. I'd expect Substring to probably be the fastest here, simply because Substring always ends up creating a string from a single chunk of the original input, whereas Remove has to at least potentially glue together a start chunk and an end chunk.

Solution 2 - C#

I know this is hyper-optimization land, but it seemed like a good excuse to kick the wheels of BenchmarkDotNet. The result of this test (on .NET Core even) is that Substring is ever so slightly faster than Remove, in this sample test: 19.37ns vs 22.52ns for Remove. So some ~16% faster.

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>();
		}
	}
}

Results:

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 |

Solution 3 - C#

I'd guess that Remove and Substring would tie for first place, since they both slurp up a fixed-size portion of the string, whereas TrimStart does a scan from the left with a test on each character and then has to perform exactly the same work as the other two methods. Seriously, though, this is splitting hairs.

Solution 4 - C#

You could profile it, if you really cared. Write a loop of many iterations and see what happens. Chances are, however, that this is not the bottleneck in your application, and TrimStart seems the most semantically correct. Strive to write code readably before optimizing.

Solution 5 - C#

In .Net Core also this works:

data = data[1..];

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmr BadawyView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Nicholas PetersenView Answer on Stackoverflow
Solution 3 - C#Marcelo CantosView Answer on Stackoverflow
Solution 4 - C#Stefan KendallView Answer on Stackoverflow
Solution 5 - C#Vasilis PlavosView Answer on Stackoverflow