Заменить несколько строковых элементов в C#


есть ли лучший способ сделать это...

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

я расширил класс string, чтобы сохранить его до одного задания, но есть ли более быстрый способ?

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

просто для удовольствия (и чтобы остановить аргументы в комментариях) Я засунул суть в бенчмаркинг различных примеров ниже.

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

оценки параметра регулярное выражение ужасно; вариант словаря вверх по самой быстрой; длинная ветреная версия замены stringbuilder немного быстрее, чем короткая рука.

8 63

8 ответов:

быстрее - нет. Более эффективно-да, если вы будете использовать StringBuilder класса. С вашей реализацией каждая операция генерирует копию строки, которая при определенных обстоятельствах может ухудшить производительность. Строки неизменяемые объекты, поэтому каждая операция просто возвращает измененную копию.

если вы ожидаете, что этот метод будет активно вызываться на нескольких Strings значительной длины, возможно, было бы лучше "перенести" его реализацию на StringBuilder класса. С этим модификация выполняется непосредственно на этом экземпляре, поэтому вы избавляетесь от ненужных операций копирования.

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

может быть, немного более читаемым?

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

добавить новое предложение в городе по поводу класса StringBuilder...

это будет более эффективным:

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

Если вам просто нужно красивое решение и не нужно экономить несколько наносекунд, как насчет сахара 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));

есть одна вещь, которая может быть оптимизирована в предложенных решениях. Имея много звонков в Replace() делает код для выполнения нескольких проходов над одной строкой. С очень длинными строками решения могут быть медленными из-за пропусков емкости кэша процессора. Может быть, стоит рассмотреть замена нескольких строк за один проход.

другой вариант использования linq-это

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

Я делаю что-то подобное, но в моем случае я делаю сериализацию/де-сериализацию, поэтому мне нужно иметь возможность идти в обоих направлениях. Я нахожу, что использование строки [] [] работает почти идентично словарю, включая инициализацию, но вы можете пойти и в другом направлении, возвращая заменители к их исходным значениям, что-то, что словарь действительно не настроен делать.

изменить: вы можете использовать Dictionary<Key,List<Values>> чтобы получить тот же результат, что и string[][]

string input = "it's worth a lot of money, if you can find a buyer.";
for (dynamic i = 0, repl = new string[,] { { "'", "''" }, { "money", "$" }, { "find", "locate" } }; i < repl.Length / 2; i++) {
    input = input.Replace(repl[i, 0], repl[i, 1]);
}