0

I need to replace all placeholders like {text} with a corresponding value from a dictionary.

This is my code:

var args = new Dictionary<string, string> {
   {"text1", "name"},
   {"text2", "Franco"}
};
saveText(Regex.Replace("Hi, my {text1} is {text2}.", @"\{(\w+)\}", m => args[m.Groups[1].Value]));

The problem is: if the text in the input string does not exist in the dictionary, it throws an exception but I rather need to replace the placeholder with the string "null".

4
  • Do you expect that the key value could contain valid Regex codes? If it does then this kind of Regex replacement won't work. Commented Jan 8, 2015 at 0:29
  • @Enigmativity why wouldn't it? Commented Jan 8, 2015 at 0:43
  • @LucasTrzesniewski - Try replacing the {text1} with {text.1} in both the key and the input string. The result of the OP's code becomes Hi, my {text.1} is Franco.. Commented Jan 8, 2015 at 1:50
  • @Enigmativity Yes, it's because of the regex used. If you want to enable this scenario, replace @"\{(\w+)\}" with @"\{(.+?)\}" and it will work. Commented Jan 8, 2015 at 8:16

3 Answers 3

5

Just expand your lambda:

var args = new Dictionary<string, string> {
   {"text1", "name"},
   {"text2", "Franco"}
};

saveText(Regex.Replace("Hi, my {text1} is {text2}.", @"\{(\w+)\}", m => {
    string value;
    return args.TryGetValue(m.Groups[1].Value, out value) ? value : "null";
}));
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that is i needed, simple and functional :D
0

I would use LINQ to create a single Func<string, string> that performs all of the replacements in one go.

Here's how:

var replace = new Dictionary<string, string>
{
    { "text1", "name" },
    { "text2", "Franco" }
}
    .Select(kvp => (Func<string, string>)
        (x => x.Replace(String.Format("{{{0}}}", kvp.Key), kvp.Value)))
    .Aggregate<Func<string, string>, Func<string, string>>(
        x => Regex.Replace(x, @"\{(\w+)\}", "null"),
        (a, f) => x => a(f(x)));

var result = replace( "Hi, my {text1} is {text2} and {text3} and {text4}.");

// result == "Hi, my name is Franco and null and null."

5 Comments

This performs one replacement per key/value pair, so it's certainly not "in one go". Also, it doesn't replace unrecognized keys with "null". Oh, and it leaves the braces too. Expected result: "Hi, my {text1} is {text2} and {text3}." -> "Hi, my name is Franco and null."
@LucasTrzesniewski - Sorry, I missed a few key points in the question. I've updated my answer and I believe it functions correctly.
@LucasTrzesniewski - As an additional note - my solution will handle cases when the key values contain Regex special characters.
Yes, that's better :) but try your solution with new Dictionary<string, string> { { "text1", "Foo {text2}" }, { "text2", "Bar {text1}" } }. The outcome won't be "Hi, my Foo {text2} is Bar {text1} and null and null." as expected. I think you're overcomplicating things here tbh ;)
@LucasTrzesniewski - Irony re over-complicating it. LOL
0

It seems the OP is trying to solve the problem of rendering a template. While it is fun to use regex, the problem of rendering templates is well addressed by template engines.

A good template language is Mustache and a good template Engine is stubble. Even if you do not harness all the power of template engine, the overall code is still concise:

using Stubble.Core.Builders;
...
var args = new Dictionary<string, string> {
   {"text1", "name"},
   {"text2", "Franco"}
};
var stubble = new StubbleBuilder().Build();
saveText(stubble.Render("Hi, my {{text1}} is {{text2}} and {{text3}} and {{text4}}")

The default behavior of stubble is to render unknown placeholders as empty. You can however add a default, e.g. a string with value "null":

var stubble = new StubbleBuilder().Configure(settings =>
{
  settings.AddValueGetter(typeof(object), (key, value, ignoreCase) => "null");
}).Build();
Dictionary<string, object> args = new Dictionary<string, object> {
  {"text1", "name"},
  {"text2", "Franco"}
};
saveText(stubble.Render("Hi, my {{text1}} is {{text2}} and {{text3}} and {{text4}}")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.