Existe um jeito melhor de fazer isso...
MyString.Trim().Replace("&", "and").Replace(",", "").Replace(" ", " ")
.Replace(" ", "-").Replace("'", "").Replace("/", "").ToLower();
Eu estendi a classe string para mantê-la em um único trabalho, mas existe uma maneira mais rápida?
public static class StringExtension
{
public static string clean(this string s)
{
return s.Replace("&", "and").Replace(",", "").Replace(" ", " ")
.Replace(" ", "-").Replace("'", "").Replace(".", "")
.Replace("eacute;", "é").ToLower();
}
}
Apenas por diversão (e para interromper os argumentos nos comentários), eu apresentei uma ideia básica comparando os vários exemplos abaixo.
A opção regex pontua terrivelmente; a opção de dicionário surge mais rápido; a versão longa do stringbuilder replace é ligeiramente mais rápida do que a mão curta.
c#
string
refactoring
immutability
Chris McKee
fonte
fonte
Respostas:
Mais rápido - não. Mais eficaz - sim, se você usar a
StringBuilder
classe. Com sua implementação, cada operação gera uma cópia de uma string que, em certas circunstâncias, pode prejudicar o desempenho. Strings são objetos imutáveis , então cada operação retorna apenas uma cópia modificada.Se você espera que esse método seja ativado ativamente em múltiplos
Strings
de comprimento significativo, pode ser melhor "migrar" sua implementação para aStringBuilder
classe. Com ele, qualquer modificação é realizada diretamente nessa instância, evitando operações de cópia desnecessárias.public static class StringExtention { public static string clean(this string s) { StringBuilder sb = new StringBuilder (s); sb.Replace("&", "and"); sb.Replace(",", ""); sb.Replace(" ", " "); sb.Replace(" ", "-"); sb.Replace("'", ""); sb.Replace(".", ""); sb.Replace("eacute;", "é"); return sb.ToString().ToLower(); } }
fonte
isso será mais eficiente:
public static class StringExtension { public static string clean(this string s) { return new StringBuilder(s) .Replace("&", "and") .Replace(",", "") .Replace(" ", " ") .Replace(" ", "-") .Replace("'", "") .Replace(".", "") .Replace("eacute;", "é") .ToString() .ToLower(); } }
fonte
Se você está simplesmente atrás de uma solução bonita e não precisa economizar alguns nanossegundos, que tal um pouco de açúcar LINQ?
var input = "test1test2test3"; var replacements = new Dictionary<string, string> { { "1", "*" }, { "2", "_" }, { "3", "&" } }; var output = replacements.Aggregate(input, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
fonte
Talvez um pouco mais legível?
public static class StringExtension { private static Dictionary<string, string> _replacements = new Dictionary<string, string>(); static StringExtension() { _replacements["&"] = "and"; _replacements[","] = ""; _replacements[" "] = " "; // etc... } public static string clean(this string s) { foreach (string to_replace in _replacements.Keys) { s = s.Replace(to_replace, _replacements[to_replace]); } return s; } }
Adicione também a sugestão do New In Town sobre StringBuilder ...
fonte
private static Dictionary<string, string> _replacements = new Dictionary<string, string>() { {"&", "and"}, {",", ""}, {" ", " "} /* etc */ };
List<Tuple<string,string>>
. Isso também muda a ordem em que as substituições são feitas E não é tão rápido quanto, por exemplos.Replace("a").Replace("b").Replace("c")
. Não use isso!Existe uma coisa que pode ser otimizada nas soluções sugeridas. Ter muitas chamadas para
Replace()
faz com que o código faça várias passagens na mesma string. Com strings muito longas, as soluções podem ser lentas devido à perda de capacidade do cache da CPU. Pode ser que se deva considerar a substituição de várias strings em uma única passagem .fonte
Outra opção usando o linq é
[TestMethod] public void Test() { var input = "it's worth a lot of money, if you can find a buyer."; var expected = "its worth a lot of money if you can find a buyer"; var removeList = new string[] { ".", ",", "'" }; var result = input; removeList.ToList().ForEach(o => result = result.Replace(o, string.Empty)); Assert.AreEqual(expected, result); }
fonte
var removeList = new List<string> { /*...*/ };
então basta chamarremoveList.ForEach( /*...*/ );
e simplificar seu código. Observe também que ele não responde totalmente à pergunta porque todas as strings encontradas são substituídas porString.Empty
.Estou fazendo algo semelhante, mas no meu caso estou fazendo a serialização / desserialização, então preciso poder ir nas duas direções. Eu descobri que usar uma string [] [] funciona quase de forma idêntica ao dicionário, incluindo a inicialização, mas você pode ir na outra direção também, retornando os substitutos aos seus valores originais, algo que o dicionário realmente não está configurado para fazer.
Editar: você pode usar
Dictionary<Key,List<Values>>
para obter o mesmo resultado que string [] []fonte
string input = "it's worth a lot of money, if you can find a buyer."; for (dynamic i = 0, repl = new string[,] { { "'", "''" }, { "money", "$" }, { "find", "locate" } }; i < repl.Length / 2; i++) { input = input.Replace(repl[i, 0], repl[i, 1]); }
fonte