Preciso remover a primeira (e SÓ a primeira) ocorrência de uma string de outra string.
Aqui está um exemplo de substituição da string "\\Iteration"
. Isto:
ProjectName \\ Iteration \\ Release1 \\ Iteration1
se tornaria isso:
ProjectName \\ Release1 \\ Iteration1
Aqui está um código que faz isso:
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;
Isso parece muito código.
Portanto, minha pergunta é a seguinte: existe uma maneira mais limpa / legível / mais concisa de fazer isso?
æ
eae
são considerados iguais. A tentativa de removerpaedia
deEncyclopædia
lançará umArgumentOutOfRangeException
, já que você está tentando remover 6 caracteres quando a substring correspondente contém apenas 5.sourceString.IndexOf(removeString, StringComparison.Ordinal)
para evitar a exceção.string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);
EDITAR: @OregonGhost está certo. Eu mesmo quebraria o script com condicionais para verificar essa ocorrência, mas estava operando sob a suposição de que as cadeias de caracteres pertencessem umas às outras por algum requisito. É possível que as regras de tratamento de exceções exigidas pelos negócios capturem essa possibilidade. Eu mesmo usaria algumas linhas extras para realizar verificações condicionais e também para torná-lo um pouco mais legível para desenvolvedores juniores que podem não ter tempo para lê-lo completamente o suficiente.
fonte
sourceString.Replace(removeString, "");
fonte
Escreveu um teste rápido TDD para isso
[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 (entrada, "", 1); diz para procurar na entrada por qualquer coisa que corresponda ao padrão, com "", 1 vez.
fonte
Você pode usar um método de extensão para se divertir. Normalmente eu não recomendo anexar métodos de extensão a uma classe de uso geral como string, mas como eu disse, isso é divertido. Peguei emprestada a resposta de @Lucke, pois não adianta reinventar a roda.
[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); } }
fonte
IsValidIBAN(this string input)
seria muito específico para tê-lo na string.Se você quiser um método simples para resolver este problema. (Pode ser usado como uma extensão)
Ver abaixo:
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); }
Uso:
string valueWithPipes = "| 1 | 2 | 3"; string valueWithoutFirstpipe = valueWithPipes.RemoveFirstInstanceOfString("|"); //Output, valueWithoutFirstpipe = " 1 | 2 | 3";
Inspirado e modificado pelas respostas de @ LukeH e @Mike.
Não se esqueça do StringComparison.Ordinal para evitar problemas com as configurações de cultura. https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html
fonte
Eu definitivamente concordo que isso é perfeito para um método de extensão, mas acho que pode ser melhorado um pouco.
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); }
Isso causa um pouco de recursão, o que é sempre divertido.
Aqui está um teste de unidade simples:
[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); }
fonte