99

有没有更好的方法来做到这一点...

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 的冗长版本比简写略快。

4

10 回答 10

142

更快 - 不。更有效 - 是的,如果您将使用该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();
    }
}
于 2009-08-24T09:27:38.360 回答
20

如果您只是追求一个漂亮的解决方案并且不需要节省几纳秒,那么一些 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));
于 2014-05-06T02:21:38.567 回答
15

这将更有效率:

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();
    }
}
于 2009-08-24T09:31:35.933 回答
11

也许更具可读性?

    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 的建议...

于 2009-08-24T09:33:27.943 回答
6

建议的解决方案中可能会优化一件事。多次调用Replace()会使代码对同一个字符串进行多次传递。对于非常长的字符串,由于 CPU 缓存容量未命中,解决方案可能会很慢。可能应该考虑一次替换多个字符串

该链接的基本内容:

static string MultipleReplace(string text, Dictionary replacements) {
            return Regex.Replace(text, 
                                    "(" + String.Join("|", adict.Keys.ToArray()) + ")",
                                    delegate(Match m) { return replacements[m.Value]; }
                                    );
        }
    // somewhere else in code
            string temp = "Jonathan Smith is a developer";
            adict.Add("Jonathan", "David");
            adict.Add("Smith", "Seruyange");
            string rep = MultipleReplace(temp, adict);


于 2014-05-21T13:21:26.643 回答
4

使用 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);
}
于 2017-11-09T11:15:24.647 回答
1

我正在做类似的事情,但就我而言,我正在做序列化/反序列化,所以我需要能够双向进行。我发现使用 string[][] 的工作方式几乎与字典相同,包括初始化,但您也可以朝另一个方向发展,将替代项返回到它们的原始值,这是字典真正没有设置的。

编辑:您可以使用Dictionary<Key,List<Values>>以获得与 string[][] 相同的结果

于 2011-09-16T22:57:31.910 回答
0

MatchEvaluator也可以使用正则表达式:

    var pattern = new Regex(@"These|words|are|placed|in|parentheses");
    var input = "The matching words in this text are being placed inside parentheses.";
    var result = pattern.Replace(input , match=> $"({match.Value})");

笔记:

  • 显然不同的表达式(如\b(\w*test\w*)\b:)可用于单词匹配。
  • 我希望它能够更加优化以找到表达式中的模式并进行替换
  • 优点是能够在进行替换时处理匹配元素
于 2021-09-23T22:20:37.580 回答
0

这基本上是Paolo Tedesco 的回答,但我想让它可重复使用。

    public class StringMultipleReplaceHelper
    {
        private readonly Dictionary<string, string> _replacements;

        public StringMultipleReplaceHelper(Dictionary<string, string> replacements)
        {
            _replacements = replacements;
        }

        public string clean(string s)
        {
            foreach (string to_replace in _replacements.Keys)
            {
                s = s.Replace(to_replace, _replacements[to_replace]);
            }
            return s;
        }
    }

需要注意的一件事是,我必须停止将其作为扩展名,删除static修饰符,然后thisclean(this string s). 我愿意接受有关如何更好地实施这一点的建议。

于 2022-02-22T11:27:52.860 回答
-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]);
}
于 2017-03-16T00:23:16.500 回答