¿Hay una mejor manera de hacer esto ...
MyString.Trim().Replace("&", "and").Replace(",", "").Replace(" ", " ")
.Replace(" ", "-").Replace("'", "").Replace("/", "").ToLower();
He ampliado la clase de cadena para mantenerla en un solo trabajo, pero ¿hay una forma más 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();
}
}
Solo por diversión (y para detener los argumentos en los comentarios), hice una evaluación comparativa de los diversos ejemplos a continuación.
La opción de expresiones regulares puntúa terriblemente; la opción de diccionario es la más rápida; la versión larga de la sustitución de stringbuilder es ligeramente más rápida que la mano corta.
c#
string
refactoring
immutability
Chris McKee
fuente
fuente
Respuestas:
Más rápido, no. Más efectivo, sí, si usa la
StringBuilder
clase. Con su implementación, cada operación genera una copia de una cadena que, bajo circunstancias, puede afectar el rendimiento. Las cadenas son objetos inmutables , por lo que cada operación solo devuelve una copia modificada.Si espera que este método sea llamado de forma activa en múltiples
Strings
de longitud significativa, sería mejor "migrar" su implementación a laStringBuilder
clase. Con él, cualquier modificación se realiza directamente en esa instancia, por lo que ahorra operaciones de copia innecesarias.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(); } }
fuente
esto será más 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(); } }
fuente
Si simplemente busca una solución bonita y no necesita ahorrar unos nanosegundos, ¿qué tal un poco de azú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));
fuente
¿Quizás un poco más legible?
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; } }
También agregue la sugerencia de New In Town sobre StringBuilder ...
fuente
private static Dictionary<string, string> _replacements = new Dictionary<string, string>() { {"&", "and"}, {",", ""}, {" ", " "} /* etc */ };
List<Tuple<string,string>>
. Esto también cambia el orden de los reemplazos y no es tan rápido como, por ejemplos.Replace("a").Replace("b").Replace("c")
. ¡No uses esto!Hay una cosa que se puede optimizar en las soluciones sugeridas. Tener muchas llamadas a
Replace()
hace que el código realice múltiples pasadas sobre la misma cadena. Con cadenas muy largas, las soluciones pueden ser lentas debido a fallas de capacidad de caché de la CPU. Puede ser que uno deba considerar reemplazar varias cadenas en una sola pasada .fuente
Otra opción que usa linq es
[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); }
fuente
var removeList = new List<string> { /*...*/ };
luego simplemente llamarremoveList.ForEach( /*...*/ );
y simplificar su código. Tenga en cuenta también que no responde completamente a la pregunta porque todas las cadenas encontradas se reemplazan conString.Empty
.Estoy haciendo algo similar, pero en mi caso estoy haciendo serialización / deserialización, así que necesito poder ir en ambas direcciones. Encuentro que usar una cadena [] [] funciona casi de manera idéntica al diccionario, incluida la inicialización, pero también puede ir en la otra dirección, devolviendo los sustitutos a sus valores originales, algo para lo que el diccionario realmente no está configurado.
Editar: puede utilizar
Dictionary<Key,List<Values>>
para obtener el mismo resultado que la cadena [] []fuente
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]); }
fuente