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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1321331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:07:14  来源:igfitidea点击:

Replace Multiple String Elements in C#

c#stringrefactoringimmutability

提问by Chris McKee

Is there a better way of doing this...

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

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

I've extended the string class to keep it down to one job but is there a quicker way?

我已经扩展了字符串类以将其缩减为一项工作,但是有没有更快的方法?

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


Just for fun (and to stop the arguments in the comments) I've shoved a gist up benchmarking the various examples below.

只是为了好玩(并停止评论中的争论),我提出了对下面各种示例进行基准测试的要点。

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

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

The regex option scores terribly; the dictionary option comes up the fastest; the long winded version of the stringbuilder replace is slightly faster than the short hand.

正则表达式选项的得分非常糟糕;字典选项出现得最快;stringbuilder 替换的长卷版本比短手略快。

采纳答案by Chris McKee

Quicker - no. More effective - yes, if you will use the StringBuilderclass. With your implementation each operation generates a copy of a string which under circumstances may impair performance. Strings are immutableobjects so each operation just returns a modified copy.

更快 - 不。更有效 - 是的,如果您将使用StringBuilder该类。在您的实现中,每个操作都会生成一个字符串的副本,这在某些情况下可能会影响性能。字符串是不可变对象,因此每个操作只返回一个修改后的副本。

If you expect this method to be actively called on multiple Stringsof significant length, it might be better to "migrate" its implementation onto the StringBuilderclass. With it any modification is performed directly on that instance, so you spare unnecessary copy operations.

如果您希望在多个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();
    }
}

回答by TheVillageIdiot

this will be more efficient:

这将更有效率:

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

回答by Paolo Tedesco

Maybe a little more readable?

也许更具可读性?

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

Also add New In Town's suggestion about StringBuilder...

还要添加 New In Town 关于 StringBuilder 的建议...

回答by sidDemure

I'm doing something similar, but in my case I'm doing serialization/De-serialization so I need to be able to go both directions. I find using a string[][] works nearly identically to the dictionary, including initialization, but you can go the other direction too, returning the substitutes to their original values, something that the dictionary really isn't set up to do.

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

Edit: You can use Dictionary<Key,List<Values>>in order to obtain same result as string[][]

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

回答by TimS

If you are simply after a pretty solution and don't need to save a few nanoseconds, how about some LINQ sugar?

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

回答by Andrej Adamenko

There is one thing that may be optimized in the suggested solutions. Having many calls to Replace()makes the code to do multiple passes over the same string. With very long strings the solutions may be slow because of CPU cache capacity misses. May be one should consider replacing multiple strings in a single pass.

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

回答by user7718176

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

回答by Luiz Felipe

Another option using linq is

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