Muszę usunąć pierwsze (i TYLKO pierwsze) wystąpienie ciągu z innego ciągu.
Oto przykład zastępujący ciąg "\\Iteration"
. To:
ProjectName \\ Iteration \\ Release1 \\ Iteration1
stałoby się:
ProjectName \\ Release1 \\ Iteration1
Oto kod, który to robi:
const string removeString = "\\Iteration";
int index = sourceString.IndexOf(removeString);
int length = removeString.Length;
String startOfString = sourceString.Substring(0, index);
String endOfString = sourceString.Substring(index + length);
String cleanPath = startOfString + endOfString;
Wydaje się, że to dużo kodu.
Moje pytanie brzmi więc: czy istnieje bardziej przejrzysty / czytelniejszy / bardziej zwięzły sposób, aby to zrobić?
æ
iae
są uważane za równe. Próba usunięciapaedia
zEncyclopædia
spowoduje wyświetlenie znakuArgumentOutOfRangeException
, ponieważ próbujesz usunąć 6 znaków, gdy pasujący podciąg zawiera tylko 5.sourceString.IndexOf(removeString, StringComparison.Ordinal)
aby uniknąć wyjątku.string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);
EDYCJA: @OregonGhost ma rację. Sam bym rozbijał skrypt warunkowymi, aby sprawdzić takie wystąpienie, ale działałem przy założeniu, że ciągi znaków zostały określone jako należące do siebie przez jakiś wymóg. Jest możliwe, że reguły obsługi wyjątków wymagane przez firmę powinny wychwycić tę możliwość. Sam użyłbym kilku dodatkowych wierszy, aby przeprowadzić testy warunkowe, a także uczynić go nieco bardziej czytelnym dla młodszych programistów, którzy mogą nie mieć czasu, aby przeczytać go wystarczająco dokładnie.
źródło
sourceString.Replace(removeString, "");
źródło
Napisałem w tym celu szybki test TDD
[TestMethod] public void Test() { var input = @"ProjectName\Iteration\Release1\Iteration1"; var pattern = @"\\Iteration"; var rgx = new Regex(pattern); var result = rgx.Replace(input, "", 1); Assert.IsTrue(result.Equals(@"ProjectName\Release1\Iteration1")); }
rgx.Replace (wejście, "", 1); mówi, aby szukać w danych wejściowych czegokolwiek pasującego do wzorca, z "", 1 raz.
źródło
Możesz użyć metody rozszerzenia dla zabawy. Zazwyczaj nie polecam dołączania metod rozszerzających do takiej klasy ogólnego przeznaczenia, jak string, ale jak powiedziałem, jest to zabawne. Pożyczyłem odpowiedź od @ Luke'a, ponieważ nie ma sensu ponownie wymyślać koła.
[Test] public void Should_remove_first_occurrance_of_string() { var source = "ProjectName\\Iteration\\Release1\\Iteration1"; Assert.That( source.RemoveFirst("\\Iteration"), Is.EqualTo("ProjectName\\Release1\\Iteration1")); } public static class StringExtensions { public static string RemoveFirst(this string source, string remove) { int index = source.IndexOf(remove); return (index < 0) ? source : source.Remove(index, remove.Length); } }
źródło
IsValidIBAN(this string input)
byłoby zbyt szczegółowe, aby mieć go na łańcuchu.Jeśli potrzebujesz prostej metody rozwiązania tego problemu. (Może być używany jako rozszerzenie)
Zobacz poniżej:
public static string RemoveFirstInstanceOfString(this string value, string removeString) { int index = value.IndexOf(removeString, StringComparison.Ordinal); return index < 0 ? value : value.Remove(index, removeString.Length); }
Stosowanie:
string valueWithPipes = "| 1 | 2 | 3"; string valueWithoutFirstpipe = valueWithPipes.RemoveFirstInstanceOfString("|"); //Output, valueWithoutFirstpipe = " 1 | 2 | 3";
Zainspirowana i zmodyfikowana odpowiedzią @ LukeH i @ Mike.
Nie zapomnij o StringComparison.Ordinal, aby zapobiec problemom z ustawieniami kultury. https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html
źródło
Zdecydowanie zgadzam się, że jest to idealne rozwiązanie dla metody przedłużania, ale myślę, że można to nieco poprawić.
public static string Remove(this string source, string remove, int firstN) { if(firstN <= 0 || string.IsNullOrEmpty(source) || string.IsNullOrEmpty(remove)) { return source; } int index = source.IndexOf(remove); return index < 0 ? source : source.Remove(index, remove.Length).Remove(remove, --firstN); }
Robi to trochę rekurencji, co zawsze jest zabawne.
Oto również prosty test jednostkowy:
[TestMethod()] public void RemoveTwiceTest() { string source = "look up look up look it up"; string remove = "look"; int firstN = 2; string expected = " up up look it up"; string actual; actual = source.Remove(remove, firstN); Assert.AreEqual(expected, actual); }
źródło