web-dev-qa-db-fra.com

Remplacer plusieurs éléments de chaîne en C #

Existe-t-il une meilleure façon de le faire...

MyString.Trim().Replace("&", "and").Replace(",", "").Replace("  ", " ")
         .Replace(" ", "-").Replace("'", "").Replace("/", "").ToLower();

J'ai étendu la classe de chaînes pour la limiter à un seul travail, mais existe-t-il un moyen plus rapide?

public static class StringExtension
{
    public static string clean(this string s)
    {
        return s.Replace("&", "and").Replace(",", "").Replace("  ", " ")
                .Replace(" ", "-").Replace("'", "").Replace(".", "")
                .Replace("eacute;", "é").ToLower();
    }
}

Juste pour le plaisir (et pour arrêter les arguments dans les commentaires), j'ai poussé un Gist jusqu'à comparer les différents exemples ci-dessous.

https://Gist.github.com/ChrisMcKee/5937656

L'option regex marque terriblement; l'option dictionnaire apparaît le plus rapidement; la version longue de la corde de remplacement est légèrement plus rapide que la main courte.

73
Chris McKee

Plus rapide - non. Plus efficace - oui, si vous utilisez la classe StringBuilder. Avec votre implémentation, chaque opération génère une copie d'une chaîne qui, dans certaines circonstances, peut nuire aux performances. Les chaînes sont des objets immuables, donc chaque opération renvoie simplement une copie modifiée.

Si vous vous attendez à ce que cette méthode soit activement appelée sur plusieurs Strings de longueur significative, il peut être préférable de "migrer" son implémentation vers la classe StringBuilder. Avec elle, toute modification est effectuée directement sur cette instance, vous évitez ainsi les opérations de copie inutiles.

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();
    }
}
105
user151323

Peut-être un peu plus lisible?

    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;
        }
    }

Ajoutez également la suggestion de New In Town à propos de StringBuilder ...

13
Paolo Tedesco

ce sera plus efficace:

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();
    }
}
11
TheVillageIdiot

Si vous recherchez simplement une jolie solution et n'avez pas besoin d'économiser quelques nanosecondes, que diriez-vous du sucre 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));
10
TimS

Il y a une chose qui peut être optimisée dans les solutions suggérées. Le fait d'avoir plusieurs appels à Replace() fait que le code effectue plusieurs passes sur la même chaîne. Avec des chaînes très longues, les solutions peuvent être lentes en raison de la capacité du cache du processeur manquante. Peut-être faut-il considérer remplacer plusieurs chaînes en une seule passe .

4
Andrej Adamenko

Je fais quelque chose de similaire, mais dans mon cas, je fais de la sérialisation/désérialisation, je dois donc pouvoir aller dans les deux sens. Je trouve que l'utilisation d'une chaîne [] [] fonctionne presque de manière identique au dictionnaire, y compris l'initialisation, mais vous pouvez aussi aller dans l'autre sens, en renvoyant les substituts à leurs valeurs d'origine, ce que le dictionnaire n'est pas vraiment configuré pour faire.

Modifier: vous pouvez utiliser Dictionary<Key,List<Values>> afin d'obtenir le même résultat que la chaîne [] []

2
sidDemure

Une autre option utilisant linq est

[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);
}
2
Luiz Felipe