在C#中替换多个字符串元素

时间:2009-08-24 09:25:05

标签: c# string refactoring immutability

有更好的方法吗?

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

我已经扩展了字符串类以使其保持一个工作,但有更快的方法吗?

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 replace的long winded版本比short hand稍快。

8 个答案:

答案 0 :(得分:97)

更快 - 没有。更有效 - 是的,如果您将使用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(); } } 类可能会更好。有了它,任何修改都直接在该实例上执行,因此您可以节省不必要的复制操作。

{{1}}

答案 1 :(得分:13)

也许更具可读性?

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

另外添加New In Town关于StringBuilder的建议......

答案 2 :(得分:11)

这将更有效:

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

答案 3 :(得分:10)

如果你只是在一个漂亮的解决方案之后并且不需要节省几纳秒,那么一些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));

答案 4 :(得分:4)

在建议的解决方案中可以优化一件事。多次调用Replace()会使代码在同一个字符串上进行多次传递。由于CPU缓存容量不足,使用非常长的字符串时,解决方案可能会很慢。可能应该考虑replacing multiple strings in a single pass

答案 5 :(得分:2)

我正在做类似的事情,但就我而言,我正在进行序列化/反序列化,所以我需要能够同时进行两个方向。我发现使用字符串[] []几乎与字典相同,包括初始化,但你也可以转向另一个方向,将替代品返回到原始值,这是字典真的没有设置的。< / p>

编辑:您可以使用Dictionary<Key,List<Values>>以获得与字符串[] []

相同的结果

答案 6 :(得分:2)

使用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);
}

答案 7 :(得分:-1)

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