208 votes

Remplacer plusieurs caractères dans une chaîne C#

Existe-t-il une meilleure façon de remplacer les cordes ?

Je suis surpris que Replace ne prenne pas en compte un tableau de caractères ou un tableau de chaînes de caractères. Je suppose que je pourrais écrire ma propre extension mais je suis curieux de savoir s'il existe un meilleur moyen intégré de faire ce qui suit ? Remarquez que le dernier remplacement est une chaîne et non un caractère.

myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n");

237voto

johnluetke Points 1077

Vous pouvez utiliser une expression régulière de remplacement.

s/[;,\t\r ]|[\n]{2}/\n/g
  • s/ au début signifie une recherche
  • Les personnages entre [ et ] sont les caractères à rechercher (dans n'importe quel ordre)
  • Le deuxième / délimite le texte à rechercher et le texte à remplacer

En anglais, cela se lit comme suit :

"Recherche de ; ou , ou \t ou \r ou (espace) ou exactement deux \n et le remplacer par \n "

En C#, vous pourriez faire ce qui suit : (après avoir importé System.Text.RegularExpressions )

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}");
pattern.Replace(myString, "\n");

2 votes

\t y \r sont inclus dans \s . Donc votre regex est équivalent à [;,\s] .

3 votes

Et \s est en fait équivalent à [ \f\n\r\t\v] Vous avez donc inclus des éléments qui n'étaient pas dans la question initiale. De plus, la question originale demande Replace("\n\n", "\n") ce que votre regex ne gère pas.

13 votes

Veuillez considérer que pour les opérations de remplacement simples qui ne sont pas configurables par un utilisateur, l'utilisation d'expressions régulières n'est pas optimale car elle est très lente par rapport aux opérations de chaînes régulières. Selon un premier article de référence que j'ai trouvé en cherchant "c# regex performance replace", elle est environ 13 fois plus lente.

137voto

Paul Walls Points 2671

Si vous vous sentez particulièrement intelligent et que vous ne voulez pas utiliser Regex :

char[] separators = new char[]{' ',';',',','\r','\t','\n'};

string s = "this;is,\ra\t\n\n\ntest";
string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
s = String.Join("\n", temp);

Vous pourriez également intégrer cette méthode dans une méthode d'extension sans trop d'efforts.

Edit : Ou alors attendez 2 minutes et je finirai par l'écrire de toute façon :)

public static class ExtensionMethods
{
   public static string Replace(this string s, char[] separators, string newVal)
   {
       string[] temp;

       temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
       return String.Join( newVal, temp );
   }
}

Et voilà...

char[] separators = new char[]{' ',';',',','\r','\t','\n'};
string s = "this;is,\ra\t\n\n\ntest";

s = s.Replace(separators, "\n");

1 votes

Très peu de mémoire, surtout pour les grandes chaînes de caractères.

0 votes

@MarcinJuraszek Lol... C'est probablement la première fois que j'entends quelqu'un prétendre que les méthodes de chaînes intégrées sont moins efficaces en termes de mémoire que les expressions régulières.

13 votes

Vous avez raison. J'aurais dû mesurer avant de poster ça. J'ai lancé un benchmark et Regex.Replace est plus de 8 fois plus lent que le multiple string.Replace appels d'affilée. et 4x plus lent que Split + Join . Voir gist.github.com/MarcinJuraszek/c1437d925548561ba210a1c6ed144‌​452

70voto

dodgy_coder Points 2778

Vous pouvez utiliser la fonction Aggregate de Linq :

string s = "the\nquick\tbrown\rdog,jumped;over the lazy fox.";
char[] chars = new char[] { ' ', ';', ',', '\r', '\t', '\n' };
string snew = chars.Aggregate(s, (c1, c2) => c1.Replace(c2, '\n'));

Voici la méthode d'extension :

public static string ReplaceAll(this string seed, char[] chars, char replacementCharacter)
{
    return chars.Aggregate(seed, (str, cItem) => str.Replace(cItem, replacementCharacter));
}

Exemple d'utilisation de la méthode d'extension :

string snew = s.ReplaceAll(chars, '\n');

26voto

ParPar Points 1584

C'est le chemin le plus court :

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");

2 votes

Cet exemple est également utile lorsque vous en avez besoin dans les initialisateurs.

10voto

John Whiter Points 176

Ohhh, l'horreur des performances ! La réponse est un peu dépassée, mais quand même...

public static class StringUtils
{
    #region Private members

    [ThreadStatic]
    private static StringBuilder m_ReplaceSB;

    private static StringBuilder GetReplaceSB(int capacity)
    {
        var result = m_ReplaceSB;

        if (null == result)
        {
            result = new StringBuilder(capacity);
            m_ReplaceSB = result;
        }
        else
        {
            result.Clear();
            result.EnsureCapacity(capacity);
        }

        return result;
    }

    public static string ReplaceAny(this string s, char replaceWith, params char[] chars)
    {
        if (null == chars)
            return s;

        if (null == s)
            return null;

        StringBuilder sb = null;

        for (int i = 0, count = s.Length; i < count; i++)
        {
            var temp = s[i];
            var replace = false;

            for (int j = 0, cc = chars.Length; j < cc; j++)
                if (temp == chars[j])
                {
                    if (null == sb)
                    {
                        sb = GetReplaceSB(count);
                        if (i > 0)
                            sb.Append(s, 0, i);
                    }

                    replace = true;
                    break;
                }

            if (replace)
                sb.Append(replaceWith);
            else
                if (null != sb)
                    sb.Append(temp);
        }

        return null == sb ? s : sb.ToString();
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X