Powiedzmy, że mamy następujący ciąg
string data= "/temp string";
Jeśli chcemy usunąć pierwszą postać, /
możemy to zrobić na wiele sposobów, takich jak:
data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);
Ale tak naprawdę nie wiem, który ma najlepszy algorytm i robi to szybciej.
Czy jest taki, który jest najlepszy, czy wszystkie są takie same?
/
?TrimStart
nie usunie pierwszego znaku, usunien
znaki od początku.Substring
jest najszybszy.TrimStart()
jest całkowicie wykluczone.Odpowiedzi:
Druga opcja tak naprawdę nie jest taka sama jak inne - jeśli ciąg ma postać „/// foo”, zmieni się w „foo” zamiast „// foo”.
Pierwsza opcja wymaga nieco więcej pracy, aby zrozumieć niż trzecia - uznałbym tę
Substring
opcję za najbardziej powszechną i czytelną.(Oczywiście każde z nich jako osobna instrukcja nie przyniesie niczego pożytecznego - musisz przypisać wynik do zmiennej, być może
data
samej).Nie wziąłbym tutaj pod uwagę wydajności, chyba że stałoby się to dla ciebie problemem - w takim przypadku jedynym sposobem, aby wiedzieć, było posiadanie przypadków testowych, a następnie łatwo jest uruchomić te przypadki testowe dla każdej opcji i porównaj wyniki. Spodziewałbym się, że będę
Substring
prawdopodobnie najszybszy tutaj, po prostu dlatego, żeSubstring
zawsze tworzy ciąg z pojedynczego fragmentu oryginalnego wejścia, podczas gdyRemove
musi przynajmniej potencjalnie skleić fragment początkowy i końcowy.źródło
Wiem, że to kraina hiperoptymalizacyjna, ale wydawało się, że to dobra wymówka, by kopać koła
BenchmarkDotNet
. Wynik tego testu (nawet w .NET Core) jestSubstring
nawet nieco szybszy niżRemove
w tym przykładowym teście: 19,37ns vs 22,52ns dlaRemove
. Więc jakieś ~ 16% szybciej.Wyniki:
źródło
Sądzę, że
Remove
iSubstring
remis na pierwszym miejscu, ponieważ obaj zasłaniają część łańcucha o stałej wielkości, podczasTrimStart
gdy skanuje od lewej z testem na każdym znaku, a następnie musi wykonać dokładnie taką samą pracę jak pozostałe dwie metody. Poważnie, to jednak dzieli włosy.źródło
Substring
jest szybszy niżRemove
, ponieważRemove
połączeniaSubstring
.Substring
iRemove
polegać na prywatnej metodzieFillSubstring
.string Remove(this string source, int from, int to) { return source.SubString(0, from) + source.SubString(to); }
System.PInvoke.EE.AllocateString
aby przydzielić docelowy ciąg znaków, a następnie wywołują,FillSubstring
aby skopiować znaki w poprzek. Czy patrzę na niewłaściwą rzecz?Substring
>Remove
). Nie zamierzam komentować dalej, ponieważ dyskusja zajęła mi wystarczająco dużo czasu.Możesz to profilować, jeśli naprawdę ci na tym zależy. Napisz pętlę wielu iteracji i zobacz, co się stanie. Są jednak szanse, że nie jest to wąskim gardłem w twojej aplikacji, a TrimStart wydaje się najbardziej semantycznie poprawny. Staraj się pisać kod czytelnie przed optymalizacją.
źródło
TrimStart
jest najmniej poprawne, ponieważ"//temp string".TrimStart('/')
będzie nie tylko usunąć pierwszy'/'
.