How to do a multiple case insensitive replace using a StringBuilder

本小妞迷上赌 提交于 2019-12-01 11:14:14
Prix

This is based off of Marc's answer the only real change is the check during the replacement and the boundary regex rule:

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

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.

Using a StringBuilder seems to be an option, but other solutions are also welcome.

Since you want case insensitive, I'd suggest (non 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;
}

DotNetFiddle Example

I think I might have something you could try. I used something similar to it for email templates

    public string replace()
    {
        string appPath = Request.PhysicalApplicationPath;
        StreamReader sr = new StreamReader(appPath + "EmailTemplates/NewMember.txt");

        string template = sr.ReadToEnd();

        template = template.Replace("<%Client_Name%>",
            first_name.Text + " " + middle_initial.Text + " " + last_name.Text);

        //Add Customer data
        template = template.Replace("<%Client_First_Name%>", first_name.Text);
        template = template.Replace("<%Client_MI%>", middle_initial.Text);
        template = template.Replace("<%Client_Last_Name%>", last_name.Text);
        template = template.Replace("<%Client_DOB%>", dob.Text);

        return template;

    }

Inside of your template you can have tags such as <% %> as place holders for the values you want

Hope this helps!

Alex Siepman

The answer of Marc Gravell: C# String replace with dictionary can be changed an little bit so it does not throws an exception when the match can not be found. In this case it simply does not replace the match.

In case the string to be replace is tokenized, this is the solution:

static readonly Regex RegExInstance = new Regex(@"\$(\w+)\$", RegexOptions.Compiled);
public string  ReplaceWithRegEx(string template, Dictionary<string, string> parameters)
{
    return RegExInstance.Replace(template, match => GetNewValue(parameters, match));
}

private string GetNewValue(Dictionary<string, string> parameters, Match match)
{
    var oldValue = match.Groups[1].Value;
    string newValue;
    var found = parameters.TryGetValue(oldValue, out newValue);
    if (found)
    {
        return newValue;
    }
    var originalValue = match.Groups[0].Value;
    return originalValue;
}

I have tested the solution with a 100.000 bytes string, 7 keys and hundreds of replacements. It uses 7 times more memory then the lenght of the string. And it took only 0.002 seconds.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!