如何使用 StringBuilder 进行多个不区分大小写的替换

Ale*_*man 3 c# stringbuilder

我有一个(大)模板,想要替换多个值。替换需要不区分大小写。还必须能够拥有模板中不存在的键。

例如:

[TestMethod]
public void ReplaceMultipleWithIgnoreCaseText()
{
    const string template = "My name is @Name@ and I like to read about @SUBJECT@ on @website@, tag  @subject@";  
    const string expected = "My name is Alex and I like to read about C# on stackoverflow.com, tag C#";
    var replaceParameters = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("@name@","Alex"),
        new KeyValuePair<string, string>("@subject@","C#"),
        new KeyValuePair<string, string>("@website@","stackoverflow.com"),
        // Note: The next key does not exist in template 
        new KeyValuePair<string, string>("@country@","The Netherlands"), 
    };
    var actual = ReplaceMultiple(template, replaceParameters);
    Assert.AreEqual(expected, actual);
}

public string ReplaceMultiple(
                  string template, 
                  IEnumerable<KeyValuePair<string, string>> replaceParameters)
{
    throw new NotImplementedException(
                  "Implementation needed for many parameters and long text.");
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果我有一个包含 30 个参数的列表和一个大模板,我不希望内存中有 30 个大字符串。使用 StringBuilder 似乎是一种选择,但也欢迎其他解决方案。

我尝试过但没有成功的解决方案

当键不在集合中时,此处找到的解决方案(C# String Replace with Dictionary )会引发异常,但我们的用户会犯错误,在这种情况下,我只想将错误的键留在文本中。例子:

static readonly Regex re = new Regex(@"\$(\w+)\$", RegexOptions.Compiled);
static void Main2()
{
    // "Name" is accidentally typed by a user as "nam". 
    string input = @"Dear $nam$, as of $date$ your balance is $amount$"; 

    var args = new Dictionary<string, string>(
        StringComparer.OrdinalIgnoreCase) {
    {"name", "Mr Smith"},
    {"date", "05 Aug 2009"},
    {"amount", "GBP200"}};


    // Works, but not case insensitive and 
    // uses a lot of memory when using a large template
    // ReplaceWithDictionary many args
    string output1 = input;
    foreach (var arg in args)
    {
        output1 = output1.Replace("$" + arg.Key +"$", arg.Value);
    }

    // Throws a KeyNotFoundException + Only works when data is tokenized
    string output2 = re.Replace(input, match => args[match.Groups[1].Value]);
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ips 5

使用 StringBuilder 似乎是一种选择,但也欢迎其他解决方案。

由于您想要不区分大小写,我建议(非 StringBuilder):

public static string ReplaceMultiple(
              string template, 
              IEnumerable<KeyValuePair<string, string>> replaceParameters)
{
    var result = template;

    foreach(var replace in replaceParameters)
    {
        var templateSplit = Regex.Split(result, 
                                        replace.Key, 
                                        RegexOptions.IgnoreCase);
        result = string.Join(replace.Value, templateSplit);
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

DotNetFiddle 示例