C# String replace with dictionary

前端 未结 8 2273
谎友^
谎友^ 2020-11-29 02:07

I have a string on which I need to do some replacements. I have a Dictionary where I have search-replace pairs defined. I have created fol

相关标签:
8条回答
  • 2020-11-29 02:48

    when using Marc Gravell's RegEx solution, first check if a token is available using i.e. ContainsKey, this to prevent KeyNotFoundException errors :

    string output = re.Replace(zpl, match => { return args.ContainsKey(match.Groups[1].Value) ? arg[match.Groups[1].Value] : match.Value; });
    

    when using the following slightly modified sample code (1st parameter has different name):

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

    this produces the following:

    "Dear $name$, as of 05 Aug 2009 your balance is GBP200"

    0 讨论(0)
  • 2020-11-29 02:50

    Why not just check whether such key exists?

    • if exists, then remove the pair, otherwise, skip this step;

    • add the same key, but now with newly desired value.

        // say, you have the following collection
        var fields = new Dictionary<string, string>();
        fields.Add("key1", "value1");
        fields.Add("key2", "value2");
        fields.Add("key3", "value3");
      
        // now, you want to add a pair "key2"/"value4"
        // or replace current value of "key2" with "value4"
        if (fields.ContainsKey("key2"))
        {
            fields.Remove("key2");
        }
        fields.Add("key2", "value4");
      
    0 讨论(0)
  • 2020-11-29 02:57

    Seems reasonable to me, except for one thing: it's order-sensitive. For instance, take an input string of "$x $y" and a replacement dictionary of:

    "$x" => "$y"
    "$y" => "foo"
    

    The results of the replacement are either "foo foo" or "$y foo" depending on which replacement is performed first.

    You could control the ordering using a List<KeyValuePair<string, string>> instead. The alternative is to walk through the string making sure you don't consume the replacements in further replace operations. That's likely to be a lot harder though.

    0 讨论(0)
  • 2020-11-29 03:04

    If the data is tokenized (i.e. "Dear $name$, as of $date$ your balance is $amount$"), then a Regex can be useful:

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

    However, without something like this, I expect that your Replace loop is probably about as much as you can do, without going to extreme lengths. If it isn't tokenized, perhaps profile it; is the Replace actually a problem?

    0 讨论(0)
  • The correct tool for this particular task is Mustache, a simple standard logicless templating language.

    There are many implementations. For this example, I'm going to use stubble:

    var stubble = new StubbleBuilder().Build();
    var dataHash = new Dictionary<string, Object>()
    {
        {"Foo","My Foo Example"},
        {"Bar",5}
    };
    
    var output = stubble.Render(
       "Hey, watch me replace this: {{Foo}} ... with example text.  Also {{bar}} is 5"
       , dataHash
    );
    
    0 讨论(0)
  • 2020-11-29 03:10

    Here's a lightly re-factored version of @Marc's great answer, to make the functionality available as an extension method to Regex:

    static void Main() 
    {
        string input = @"Dear $name$, as of $date$ your balance is $amount$";
        var args = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        args.Add("name", "Mr Smith");
        args.Add("date", "05 Aug 2009");
        args.Add("amount", "GBP200");
    
        Regex re = new Regex(@"\$(\w+)\$", RegexOptions.Compiled);
        string output = re.replaceTokens(input, args);
    
        // spot the LinqPad user // output.Dump();
    }
    
    public static class ReplaceTokensUsingDictionary
    {
        public static string replaceTokens(this Regex re, string input, IDictionary<string, string> args)
        {
            return re.Replace(input, match => args[match.Groups[1].Value]);
        }
    }
    
    0 讨论(0)
提交回复
热议问题