2010-02-02 4 views
18

J'ai une chaîne à partir de laquelle je dois supprimer les caractères suivants: '\ r', '\ n' et '\ t'. J'ai essayé trois façons différentes de supprimer ces caractères et les ai comparés afin d'obtenir la solution la plus rapide.Le moyen le plus rapide de supprimer les caractères de la chaîne

Après sont les méthodes et il temps d'exécution quand je les ai couru 1000000 fois:

Il devrait être solution la plus rapide si j'ai 1 ou 2 car pour enlever. Mais comme je l'ai mis plus char, il commence à prendre plus de temps

str = str.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("\t", string.Empty); 

Temps d'exécution = 1695

Pour 1 ou 2 char, ce fut plus lent alors String.Replace, mais pour 3 car il a montré de meilleures performances.

string[] split = str.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.None); 
str = split.Aggregate<string>((str1, str2) => str1 + str2); 

Temps d'exécution = 1030

Le plus lent de tous, même avec 1 caractère. Peut-être que mon expression régulière n'est pas la meilleure.

str = Regex.Replace(str, "[\r\n\t]", string.Empty, RegexOptions.Compiled); 

Temps d'exécution = 3500

Ce sont les trois solutions que je suis venu avec. Y a-t-il une solution meilleure et plus rapide que tout le monde connaisse ici, ou des améliorations que je peux faire dans ce code?

Chaîne que j'ai utilisé pour l'analyse comparative:

StringBuilder builder = new StringBuilder(); 
     builder.AppendFormat("{0}\r\n{1}\t\t\t\r\n{2}\t\r\n{3}\r\n{4}\t\t\r\n{5}\r\n{6}\r\n{7}\r\n{8}\r\n{9}", 
     "SELECT ", 
     "[Extent1].[CustomerID] AS [CustomerID], ", 
     "[Extent1].[NameStyle] AS [NameStyle], ", 
     "[Extent1].[Title] AS [Title], ", 
      "[Extent1].[FirstName] AS [FirstName], ", 
      "[Extent1].[MiddleName] AS [MiddleName], ", 
      "[Extent1].[LastName] AS [LastName], ", 
      "[Extent1].[Suffix] AS [Suffix], ", 
      "[Extent1].[CompanyName] AS [CompanyName], ", 
      "[Extent1].[SalesPerson] AS [SalesPerson], "); 
     string str = builder.ToString(); 

Répondre

16

Voici la version non sécurisée ultra-rapide, version 2.

public static unsafe string StripTabsAndNewlines(string s) 
    { 
     int len = s.Length; 
     char* newChars = stackalloc char[len]; 
     char* currentChar = newChars; 

     for (int i = 0; i < len; ++i) 
     { 
      char c = s[i]; 
      switch (c) 
      { 
       case '\r': 
       case '\n': 
       case '\t': 
        continue; 
       default: 
        *currentChar++ = c; 
        break; 
      } 
     } 
     return new string(newChars, 0, (int)(currentChar - newChars)); 
    } 

Et voici les points de référence (le temps de dépouiller 1000000 cordes en ms)

 cornerback84's String.Replace:   9433 
    Andy West's String.Concat:    4756 
    AviJ's char array:      1374 
    Matt Howells' char pointers:   1163
+1

Oui c'est. Temps d'exécution = 195 – ata

+3

btw, vous avez besoin d'une nouvelle machine: P – ata

+1

C'est un Xeon récent - nos benchmarks sont probablement configurés différemment. –

2

Looping par la chaîne et en utilisant (un seul) StringBuilder (avec l'argument constructeur proprement dit, afin d'éviter les allocations de mémoire inutiles) pour créer une nouvelle chaîne pourrait Être plus rapide.

2
String.Join(null, str.Split(new char[] { '\t', '\r', '\n' }, 
    StringSplitOptions.None)); 

pourrait vous donner une augmentation de la performance sur l'utilisation Aggregate() depuis Join() est conçu pour les chaînes.

EDIT:

En fait, cela pourrait être encore mieux:

String.Concat(str.Split(new char[] { '\t', '\r', '\n' }, 
    StringSplitOptions.None)); 
+0

exécutio n temps = 754. Merci – ata

+0

Nice! J'ai mis à jour ma réponse pour utiliser Concat() à la place. Peut-être la peine d'essayer. –

+0

Il y avait une légère amélioration lors de l'utilisation de String.Concat. Maintenant, temps d'exécution = 734 – ata

8

Je crois que vous obtiendrez les meilleures performances possibles en composant la nouvelle chaîne comme un tableau de caractères et de convertir seulement elle à une chaîne lorsque vous avez terminé, comme ceci:

string s = "abc"; 
int len = s.Length; 
char[] s2 = new char[len]; 
int i2 = 0; 
for (int i = 0; i < len; i++) 
{ 
    char c = s[i]; 
    if (c != '\r' && c != '\n' && c != '\t') 
     s2[i2++] = c; 
} 
return new String(s2, 0, i2); 

EDIT: en utilisant string (s2, 0, i2) au lieu de Trim(), par suggestion

+0

Une correction, vous devez faire new String (s2) .TrimEnd ('\ 0'); Et le temps d'exécution = 309. Génial – ata

+2

En fait j'ai fait une petite modification. Vous gardez déjà la longueur du nouveau tableau, c'est-à-dire i2. Donc plutôt que de rognage, vous pouvez utiliser return new String (s2, 0, i2); Cela amène le temps d'exécution à 255 – ata

1

essayer cette

string str = "something \tis \nbetter than nothing"; 
string removeChars = new String(new Char[]{'\n', '\t'}); 
string newStr = new string(str.ToCharArray().Where(c => !removeChars.Contains(c)).ToArray()); 
+3

Temps d'exécution = 27020. – ata

+1

LINQ est le travail du diable! –

0
string str; 
str = str.Replace(Environment.NewLine, string.Empty).Replace("\t", string.Empty); 
+1

Ceci n'est pas différent de la version SLOW dans la réponse acceptée. L'OP demande le plus rapide. –

2

Encore plus rapide:

public static string RemoveMultipleWhiteSpaces(string s) 
    { 
     char[] sResultChars = new char[s.Length]; 

     bool isWhiteSpace = false; 
     int sResultCharsIndex = 0; 

     for (int i = 0; i < s.Length; i++) 
     { 
      if (s[i] == ' ') 
      { 
       if (!isWhiteSpace) 
       { 
        sResultChars[sResultCharsIndex] = s[i]; 
        sResultCharsIndex++; 
        isWhiteSpace = true; 
       } 
      } 
      else 
      { 
       sResultChars[sResultCharsIndex] = s[i]; 
       sResultCharsIndex++; 
       isWhiteSpace = false; 
      } 
     } 

     return new string(sResultChars, 0, sResultCharsIndex); 
    } 
+0

avez-vous des repères? – Julian

Questions connexes