c# - tag - Limpiar la cuerda? ¿Hay alguna forma mejor de hacerlo?
que significa calibre 5 en tag heuer (8)
¡Este es aún más rápido!
utilizar:
string dirty=@"tfgtf$@$%gttg%$% 664%$";
string clean = dirty.Clean();
public static string Clean(this String name)
{
var namearray = new Char[name.Length];
var newIndex = 0;
for (var index = 0; index < namearray.Length; index++)
{
var letter = (Int32)name[index];
if (!((letter > 96 && letter < 123) || (letter > 64 && letter < 91) || (letter > 47 && letter < 58)))
continue;
namearray[newIndex] = (Char)letter;
++newIndex;
}
return new String(namearray).TrimEnd();
}
Estoy usando este método para limpiar la cadena
public static string CleanString(string dirtyString)
{
string removeChars = " ?&^$#@!()+-,:;<>’/'-_*";
string result = dirtyString;
foreach (char c in removeChars)
{
result = result.Replace(c.ToString(), string.Empty);
}
return result;
}
Este método funciona bien ... PERO hay un error de rendimiento en este método. Cada vez que paso la cadena, todos los caracteres pasan en bucle, si tengo una cadena grande, entonces tomaría mucho tiempo devolver el objeto.
¿Hay alguna otra forma mejor de hacer lo mismo? Como en LINQ o JQUERY / Javascript
Cualquier sugerencia sería apreciada.
No puedo dedicar tiempo a la prueba de ácido, pero esta línea no limpió las barras como se desea.
HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’/'-_*");
Tuve que agregar barras individuales y escapar de la barra invertida
HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’''-_*");
removeChars.Add(''/'');
removeChars.Add(''//');
No sé si, en cuanto al rendimiento, usar Regex
o LINQ sería una mejora.
Algo que podría ser útil, sería crear la nueva cadena con un StringBuilder
lugar de usar una string.Replace
cada vez:
using System.Linq;
using System.Text;
static class Program {
static void Main(string[] args) {
const string removeChars = " ?&^$#@!()+-,:;<>’/'-_*";
string result = "x&y(z)";
// specify capacity of StringBuilder to avoid resizing
StringBuilder sb = new StringBuilder(result.Length);
foreach (char x in result.Where(c => !removeChars.Contains(c))) {
sb.Append(x);
}
result = sb.ToString();
}
}
OK, considera la siguiente prueba:
public class CleanString
{
//by MSDN http://msdn.microsoft.com/en-us/library/844skk0h(v=vs.71).aspx
public static string UseRegex(string strIn)
{
// Replace invalid characters with empty strings.
return Regex.Replace(strIn, @"[^/w/.@-]", "");
}
// by Paolo Tedesco
public static String UseStringBuilder(string strIn)
{
const string removeChars = " ?&^$#@!()+-,:;<>’/'-_*";
// specify capacity of StringBuilder to avoid resizing
StringBuilder sb = new StringBuilder(strIn.Length);
foreach (char x in strIn.Where(c => !removeChars.Contains(c)))
{
sb.Append(x);
}
return sb.ToString();
}
// by Paolo Tedesco, but using a HashSet
public static String UseStringBuilderWithHashSet(string strIn)
{
var hashSet = new HashSet<char>(" ?&^$#@!()+-,:;<>’/'-_*");
// specify capacity of StringBuilder to avoid resizing
StringBuilder sb = new StringBuilder(strIn.Length);
foreach (char x in strIn.Where(c => !hashSet.Contains(c)))
{
sb.Append(x);
}
return sb.ToString();
}
// by SteveDog
public static string UseStringBuilderWithHashSet2(string dirtyString)
{
HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’/'-_*");
StringBuilder result = new StringBuilder(dirtyString.Length);
foreach (char c in dirtyString)
if (removeChars.Contains(c))
result.Append(c);
return result.ToString();
}
// original by patel.milanb
public static string UseReplace(string dirtyString)
{
string removeChars = " ?&^$#@!()+-,:;<>’/'-_*";
string result = dirtyString;
foreach (char c in removeChars)
{
result = result.Replace(c.ToString(), string.Empty);
}
return result;
}
// by L.B
public static string UseWhere(string dirtyString)
{
return new String(dirtyString.Where(Char.IsLetterOrDigit).ToArray());
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
var dirtyString = "sdfdf.dsf8908()=(=(sadfJJLef@ssyd€sdöf////fj()=/§(§&/(/"&sdfdf.dsf8908()=(=(sadfJJLef@ssyd€sdöf////fj()=/§(§&/(/"&sdfdf.dsf8908()=(=(sadfJJLef@ssyd€sdöf";
var sw = new Stopwatch();
var iterations = 50000;
sw.Start();
for (var i = 0; i < iterations; i++)
CleanString.<SomeMethod>(dirtyString);
sw.Stop();
Debug.WriteLine("CleanString.<SomeMethod>: " + sw.ElapsedMilliseconds.ToString());
sw.Reset();
....
<repeat>
....
}
}
Salida
CleanString.UseReplace: 791
CleanString.UseStringBuilder: 2805
CleanString.UseStringBuilderWithHashSet: 521
CleanString.UseStringBuilderWithHashSet2: 331
CleanString.UseRegex: 1700
CleanString.UseWhere: 233
Conclusión
Probablemente no importa qué método uses.
La diferencia de tiempo entre el UseWhere
ayunas ( UseWhere
: 233ms) y el más lento ( UseStringBuilder
: 2805ms) es de 2572ms cuando se le llama 50000 (!) Veces seguidas. Probablemente no deba preocuparse por ello si no ejecuta el método con tanta frecuencia.
Pero si lo hace, use el método UseWhere
(escrito por LB); Pero también tenga en cuenta que es ligeramente diferente.
Quizás ayude a explicar primero el ''por qué'' y luego el ''qué''. La razón por la que está obteniendo un rendimiento lento es porque c # copia y reemplaza las cadenas para cada reemplazo. Desde mi experiencia en el uso de Regex en .NET no siempre es mejor, aunque en la mayoría de los escenarios (creo que incluir este) probablemente funcionará bien.
Si realmente necesito rendimiento, por lo general no lo dejo a la suerte y solo le digo al compilador exactamente lo que quiero: es decir: cree una cadena con el límite superior de caracteres y copie todos los caracteres que necesite. También es posible reemplazar el hashset con un switch / caja o matriz, en cuyo caso podría terminar con una tabla de salto o búsqueda de matriz, que es aún más rápida.
La solución "pragmática" mejor, pero rápida es:
char[] data = new char[dirtyString.Length];
int ptr = 0;
HashSet<char> hs = new HashSet<char>() { /* all your excluded chars go here */ };
foreach (char c in dirtyString)
if (!hs.Contains(c))
data[ptr++] = c;
return new string(data, 0, ptr);
Por cierto: esta solución es incorrecta cuando se desean procesar caracteres Unicode de alta sustitución, pero se pueden adaptar fácilmente para incluir estos caracteres.
-Stefan.
Si lo que buscas es puramente velocidad y eficiencia, te recomendaría hacer algo como esto:
public static string CleanString(string dirtyString)
{
HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’/'-_*");
StringBuilder result = new StringBuilder(dirtyString.Length);
foreach (char c in dirtyString)
if (!removeChars.Contains(c)) // prevent dirty chars
result.Append(c);
return result.ToString();
}
RegEx es ciertamente una solución elegante, pero agrega sobrecarga adicional. Al especificar la longitud inicial del generador de cadenas, solo tendrá que asignar la memoria una vez (y una segunda vez para el ToString
al final). Esto reducirá el uso de la memoria y aumentará la velocidad, especialmente en cadenas más largas.
Sin embargo, como dijo LB, si está usando esto para codificar correctamente el texto que está vinculado a la salida HTML, debe usar HttpUtility.HtmlEncode
lugar de hacerlo usted mismo.
use regex [?&^$#@!()+-,:;<>''/'-_*]
para reemplazar con una cadena vacía