替代多个 String.Replaces [重复]

Posted

技术标签:

【中文标题】替代多个 String.Replaces [重复]【英文标题】:Alternative to multiple String.Replaces [duplicate] 【发布时间】:2012-08-13 23:52:14 【问题描述】:

我的代码连续多次使用String.Replace

mystring = mystring.Replace("somestring", variable1);
mystring = mystring.Replace("somestring2", variable2);
mystring = mystring.Replace("somestring3", variable1);

我怀疑有更好更快的方法来做到这一点。你有什么建议?

【问题讨论】:

如果variable1 包含文本"somestring2",那么您的首选行为是什么?或者如果variable1"g2"mystring"somestrinsomestring",那么首选的行为是什么? 【参考方案1】:

对于“简单”的替代方案,只需使用 StringBuilder....

StringBuilder sb = new StringBuilder("11223344");

string myString =
    sb
      .Replace("1", string.Empty)
      .Replace("2", string.Empty)
      .Replace("3", string.Empty)
      .ToString();

【讨论】:

这样更容易吗?我看到的唯一好处是它可以减少对 GC 的压力。 @Daniel Hilgarth 我所说的“更简单”的意思是实现起来仍然很简单,但是在 StringBuiler 上将替换链接在一起比在常规字符串上调用它“更好更快”并且不包括下面列出的一些正则表达式解决方案的复杂性。 这似乎是所提出的解决方案中可读性最强的。 如果需要设置条件就不好了 答案是 44 吗?【参考方案2】:

我们是否正在设法使这更难了解正在发生的事情?

如果是这样,正则表达式是你的朋友

var replacements = new Dictionary<string,string>()

   "somestring",someVariable1,
   "anotherstring",someVariable2
;

var regex = new Regex(String.Join("|",replacements.Keys.Select(k => Regex.Escape(k))));
var replaced = regex.Replace(input,m => replacements[m.Value]);

直播:http://rextester.com/SXXB8348

【讨论】:

看起来不错,但是在编译正则表达式时,您需要在 dic 键周围调用 Regex.Escape。另请注意,它在技术上不会做同样的事情。它可能适用于 OP 的测试用例,但理论上,如果您有类似的情况,将“1”替换为“2”,然后将“2”替换为“3”,OP 的代码将导致每个“1”变为“3”而你的最终会导致“2”。只要您实际上没有用 OP 的示例替换之前迭代中已替换的内容,那么这将正常工作。 @Servy - 你说得很好。但是,我的第一句话应该指出,这是一种非常糟糕的多次替换方式。 @Jamiec:这有什么问题?它可能只需要读取字符串一次,只需复制字符串一次,让您轻松查找整个单词,让您对单词进行适当的大写,并让您执行转义字符串之类的操作(例如&amp;amp;=> &amp;amp;, "=>&amp;quot;) 无需担心替换发生的顺序。 这(不幸的是)比多次调用 string.Replace() 慢得多。我也在寻找一种更快的方法来做到这一点;多次循环一个字符串似乎很浪费。 此 RegEx 解决方案只通过一次即可正确替换所有项目。在某些情况下(比如我的),这是唯一的选项,调用 .Replace 不起作用。为什么?考虑变量 1 部分包含字符串“somestring2”的情况。然后第二个 .Replace 最终会破坏您想要替换的第一件事,等等。【参考方案3】:

您至少可以将这些语句链接起来:

mystring = mystring.Replace("somestring", variable1)
                   .Replace("somestring2", variable2)
                   .Replace("somestring3", variable3); 

【讨论】:

【参考方案4】:

拨打Replace 三次不仅是一个有效的答案,它可能是首选:

RegEx 需要三个步骤:解析、执行、公式化。但是String.Replace 是硬编码的,因此在许多情况下它具有出色的速度。复杂的 RegEx 不如格式良好的 Replace 语句链具有可读性。 (比较Jonathan的解决方案和Daniel的解决方案)

如果您仍然不相信Replace 更适合您的情况,那就来一场比赛吧!并排尝试这两种方法并使用Stopwatch 来查看您在使用数据时节省了多少毫秒。

但是DON'T optimize prematurely!任何开发人员都更喜欢可读性和可维护性,而不是执行速度***毫秒的神秘意大利面条。

【讨论】:

【参考方案5】:

这篇文章Regex: replace multiple strings in a single pass with C#可能会有所帮助:

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

【讨论】:

这与 Jamiec 的回答基本相同,但没有(必需的)转义。【参考方案6】:

取决于您的数据的组织方式(您要替换的内容)或您拥有的数据数量;数组和循环可能是个好方法。

string[] replaceThese = "1", "2", "3";
string data = "replace1allthe2numbers3";

foreach (string curr in replaceThese)

    data = data.Replace(curr, string.Empty);

【讨论】:

【参考方案7】:

如果您不想使用 RegEx,请将此类添加到您的项目中, 它使用扩展方法“MultipleReplace”:

public static class StringExtender

    public static string MultipleReplace(this string text, Dictionary<string, string> replacements)
    
        string retVal = text;
        foreach (string textToReplace in replacements.Keys)
        
            retVal = retVal.Replace(textToReplace, replacements[textToReplace]);
        
        return retVal;
    

那么你就可以使用这段代码了:

 string mystring = "foobar";

 Dictionary<string, string> stringsToReplace = new Dictionary<string,string>();
 stringsToReplace.Add("somestring", variable1);
 stringsToReplace.Add("somestring2", variable2);
 stringsToReplace.Add("somestring3", variable1);

 mystring = mystring.MultipleReplace(stringsToReplace);

【讨论】:

赞成这个。它允许您从数据表中构建过滤器,这非常有用。所以当你有很多过滤器(在我的例子中是 50 个)并且你有 1k 个句子要通过时,这就是猫的喵喵声。【参考方案8】:

我首选的方法是使用Regex 的强大功能来解决多重替换问题。这种方法的唯一问题是您只能选择一个 string 来替换。

以下内容会将所有'/'':' 替换为'-' 以生成有效的文件名。

Regex.Replace("invalid:file/name.txt", @"[/:]", "-");

【讨论】:

以上是关于替代多个 String.Replaces [重复]的主要内容,如果未能解决你的问题,请参考以下文章

本地通知替代周重复

List subList()方法缺陷及替代方案

List subList()方法缺陷及替代方案

多重继承的替代方案[重复]

Mozilla中的InnerText替代品[重复]

Windows下iOS开发的替代方案[重复]