2012-07-18 5 views
7

Ho bisogno di rimuovere caratteri da una stringa che non è nella gamma Ascii da 32 a 175, qualsiasi altra cosa deve essere rimossa.Un modo migliore per rimuovere caratteri che non sono ASCII Da 32 a 175 C#

Non so se RegExp può essere la soluzione migliore invece di utilizzare qualcosa come .replace() o .remove() che passa ogni carattere non valido o qualcos'altro.

Qualsiasi aiuto sarà apprezzato.

+0

Non puoi semplicemente rimuoverli con la normale indicizzazione delle stringhe? La stringa di destinazione può essere allocata come la stessa lunghezza della stringa di origine, in quanto è garantita la stessa lunghezza o minore. Quindi copiare solo caratteri validi in un ciclo? Sono solo due i confronti da verificare validi. –

+0

E un'altra copia di 'char []' perché la stringa sarebbe della stessa lunghezza di prima, solo con padding zero in questo modo. – Joey

risposta

16

È possibile utilizzare

Regex.Replace(myString, @"[^\x20-\xaf]+", ""); 

La regex qui è costituito da una classe di caratteri ([...]) composto da tutti i caratteri non (^ al via della classe) nella gamma di U + 0020 a U + 00AF (32-175, espresso in notazione esadecimale). Per quanto riguarda le espressioni regolari, questo è piuttosto basilare, ma potrebbe essere difficile convincere qualcuno che non lo conosce molto bene.

Ma si può andare un altro percorso così:

new string(myString.Where(c => (c >= 32) && (c <= 175)).ToArray()); 

Questo dipende probabilmente in gran parte su ciò che si è più a suo agio con la lettura. Senza troppe esperienze regex direi che la seconda sarebbe più chiara.

Qualche misurazioni delle prestazioni, 10000 colpi ciascuno, in pochi secondi:

2000 characters, the first 143 of which are between 32 and 175 
    Regex without +       4.1171 
    Regex with +        0.4091 
    LINQ, where, new string     0.2176 
    LINQ, where, string.Join     0.2448 
    StringBuilder (xanatos)     0.0355 
    LINQ, horrible (HatSoft)     0.4917 
2000 characters, all of which are between 32 and 175 
    Regex without +       0.4076 
    Regex with +        0.4099 
    LINQ, where, new string     0.3419 
    LINQ, where, string.Join     0.7412 
    StringBuilder (xanatos)     0.0740 
    LINQ, horrible (HatSoft)     0.4801 

Quindi sì, i miei approcci sono il più lento :-). Probabilmente dovresti andare con la risposta di xanatos e avvolgerla in un metodo con un nome bello e chiaro. Per uso in linea o cose veloci e sporche o in cui le prestazioni non contano, probabilmente utilizzerei la regex.

+0

Dovresti usare '+' per renderlo più veloce –

+0

grazie, l'approccio select che è una buona opzione, la regex anche per analizzarlo e sapere di più su di esso. – FabianSilva

+0

wow bel test delle prestazioni, vedo che xanatos uno è il migliore se devi rimuovere i caratteri da un grande testo, grazie per aver dedicato del tempo per testarlo, nel mio caso rimuoverò i caratteri dalla stringa corta e sembra che linq sia il modo andare per me, non il più performante, non il più breve da scrivere, ma facile da applicare/scrivere in una frase di 1 riga :) grazie ancora a te, xanatos e tutti gli utenti che hanno risposto – FabianSilva

3

Usa regex [^\x20-\xAF]+ e sostituirlo con stringa vuota ""

Regex.Replace(str, @"[^\x20-\xAF]+", ""); 
7

Perché penso che se non sai come scrivere una Regex non si dovrebbe usare, soprattutto per una cosa così semplice:

var sb = new StringBuilder(); 

foreach (var c in str) 
{ 
    if (c >= 32 && c <= 175) 
    { 
     sb.Append(c); 
    } 
} 

var str2 = str.ToString(); 
+0

Questo è quello che pensavo. Una chiamata regex sembra un po 'OTT per questo? –

+0

Ho qualcosa di molto simile a questo, ad eccezione di una sezione aggiuntiva che tenta di trasformare l'alta ascii comune nell'alternativa bassa ascii, cioè "" 'in' "' – asawyer

+0

@FabianSilva Non credo che il modo migliore per imparare qualcosa sia vai a una bacheca e chiedi "puoi scriverlo per me in una lingua che non conosco?" – xanatos

1

ne dite di usare LINQ in questo modo

string text = (from c in "AAA hello aaaa #### Y world" 
       let i = (int) c where i < 32 && i > 175 select c) 
       .Aggregate("", (current, c) => current + c); 
+0

grazie per la risposta, la tua espressione linq è una buona soluzione ma mi sembra che l'espressione di joey sia più facile da capire. – FabianSilva

+0

@FabianSilva lol bella risposta – HatSoft

+0

grazie per questa soluzione alternativa utilizzando let e aggregare – FabianSilva

1
static unsafe string TrimRange(string str, char from, char to) 
{ 
    int count = 0; 

    for (int i = 0; i < str.Length; i++) 
    { 
     char ch = str[i]; 

     if ((ch >= from) && (ch <= to)) 
     { 
      count++; 
     } 
    } 

    if (count == 0) 
     return String.Empty; 

    if (count == str.Length) 
     return str; 

    char * result = stackalloc char[count]; 

    count = 0; 

    for (int i = 0; i < str.Length; i++) 
    { 
     char ch = str[i]; 

     if ((ch >= from) && (ch <= to)) 
     { 
      result[count ++] = ch; 
     } 
    } 

    return new String(result, 0, count); 
} 
Problemi correlati