如何使用StringBuilder进行大小写不敏感的替换 [英] How to do a multiple case insensitive replace using a StringBuilder

查看:44
本文介绍了如何使用StringBuilder进行大小写不敏感的替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a (large) template and want to replace multiple values. The replacement needs to be done case insensitive. It must also be possible to have keys that does not exist in the template.

例如:

[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.");
}

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

Note that if I have a list of 30 parameters and a large template, I do not want 30 large strings in memory. Using a StringBuilder seems to be an option, but other solutions are also welcome.

我尝试过但无法解决的解决方案

此处找到的解决方案(用字典替换C#字符串)引发异常当密钥不在集合中,但是我们的用户犯错时,在这种情况下,我只想在文本中保留wromg密钥.示例:

Solution found here (C# String replace with dictionary) throws an exception when a key is not in the colletion, but our users makes mistakes and in that case I want to just leave the wromg key in the text. Example:

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

推荐答案

这是基于Marc的回答,唯一真正的变化是在替换期间检查边界正则表达式规则:

static readonly Regex re = new Regex(@"\b(\w+)\b", RegexOptions.Compiled);
static void Main(string[] args)
{
    string input = @"Dear Name, as of dAte your balance is amounT!";
    var replacements = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
    {
        {"name", "Mr Smith"},
        {"date", "05 Aug 2009"},
        {"amount", "GBP200"}
    };
    string output = re.Replace(input, match => replacements.ContainsKey(match.Groups[1].Value) ? replacements[match.Groups[1].Value] : match.Groups[1].Value);
}

这是5000次迭代测试的基准,还没有研究内存或其他任何东西.

And here is a 5000 iterations test benchmark, have not looked at memory or anything else.

替换功能是您已将其选中为可接受答案的功能.

Replacement function is the one you have checked as the accepted answer.

这篇关于如何使用StringBuilder进行大小写不敏感的替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆