Je dois supprimer la première (et UNIQUEMENT la première) occurrence d'une chaîne d'une autre chaîne.
Voici un exemple de remplacement de la chaîne "\\Iteration"
. Ce:
Nom du projet \\ Iteration \\ Release1 \\ Iteration1
deviendrait ceci:
Nom du projet \\ Release1 \\ Iteration1
Voici un code qui fait cela:
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;
Cela semble beaucoup de code.
Ma question est donc la suivante: existe-t-il un moyen plus propre / plus lisible / plus concis de le faire?
æ
etae
sont considérés comme égaux. Tenter de supprimerpaedia
deEncyclopædia
lèvera unArgumentOutOfRangeException
, puisque vous essayez de supprimer 6 caractères alors que la sous-chaîne correspondante ne contient que 5.sourceString.IndexOf(removeString, StringComparison.Ordinal)
pour éviter l'exception.string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);
EDIT: @OregonGhost a raison. Je briserais moi-même le script avec des conditions pour vérifier une telle occurrence, mais j'opérais en supposant que les chaînes étaient données pour appartenir les unes aux autres par une exigence. Il est possible que les règles de gestion des exceptions requises par l'entreprise attrapent cette possibilité. J'utiliserais moi-même quelques lignes supplémentaires pour effectuer des vérifications conditionnelles et aussi pour le rendre un peu plus lisible pour les développeurs juniors qui pourraient ne pas prendre le temps de le lire suffisamment complètement.
la source
sourceString.Replace(removeString, "");
la source
A écrit un test TDD rapide pour cela
[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 (entrée, "", 1); dit de chercher en entrée tout ce qui correspond au modèle, avec "", 1 fois.
la source
Vous pouvez utiliser une méthode d'extension pour le plaisir. En général, je ne recommande pas d'attacher des méthodes d'extension à une classe à usage général comme string, mais comme je l'ai dit, c'est amusant. J'ai emprunté la réponse de @ Luke car il ne sert à rien de réinventer la roue.
[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); } }
la source
IsValidIBAN(this string input)
serait trop spécifique pour l'avoir sur une chaîne.Si vous souhaitez une méthode simple pour résoudre ce problème. (Peut être utilisé comme extension)
Voir ci-dessous:
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); }
Usage:
string valueWithPipes = "| 1 | 2 | 3"; string valueWithoutFirstpipe = valueWithPipes.RemoveFirstInstanceOfString("|"); //Output, valueWithoutFirstpipe = " 1 | 2 | 3";
Inspiré et modifié des réponses de @ LukeH et @ Mike.
N'oubliez pas StringComparison.Ordinal pour éviter les problèmes avec les paramètres de culture. https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html
la source
Je suis tout à fait d'accord pour dire que c'est parfait pour une méthode d'extension, mais je pense que cela peut être amélioré un peu.
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); }
Cela fait un peu de récursivité, ce qui est toujours amusant.
Voici également un test unitaire simple:
[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); }
la source