views:

2203

answers:

8

Hi,

I want in a good performance way (I hope) replace a named parameter in my string to a named parameter from code, example, my string:

"Hi {name}, do you like milk?"

How could I replace the {name} by code, Regular expressions? To expensive? Which way do you recommend?

How do they in example NHibernates HQL to replace :my_param to the user defined value? Or in ASP.NET (MVC) Routing that I like better, "{controller}/{action}", new { controller = "Hello", ... }?

+11  A: 

Have you confirmed that regular expressions are too expensive?

The cost of regular expressions is greatly exaggerated. For such a simple pattern performance will be quite good, probably only slightly less good than direct search-and-replace, in fact. Also, have you experimented with the Compiled flag when constructing the regular expression?

That said, can't you just use the simplest way, i.e. Replace?

string varname = "name";
string pattern = "{" + varname + "}";
Console.WriteLine("Hi {name}".Replace(pattern, "Mike"));
Konrad Rudolph
+1 for doing things the simple way :)
Jon Skeet
(Although you mean Replace(pattern, "Mike"))
Jon Skeet
@Jon: Thanks. Why use a compiler when you've got a Jon? ;-)
Konrad Rudolph
A: 

A compiled regex might do the trick , especially if there are many tokens to be replaced. If there are just a handful of them and performance is key, I would simply find the token by index and replace using string functions. Believe it or not this will be faster than a regex.

Andrew Hare
+4  A: 

Regex is certainly a viable option, especially with a MatchEvaluator:

    Regex re = new Regex(@"\{(\w*?)\}", RegexOptions.Compiled); // store this...

    string input = "Hi {name}, do you like {food}?";

    Dictionary<string, string> vals = new Dictionary<string, string>();
    vals.Add("name", "Fred");
    vals.Add("food", "milk");

    string q = re.Replace(input, delegate(Match match)
    {
        string key = match.Groups[1].Value;
        return vals[key];
    });
Marc Gravell
Damn... How'd you get that 18 minutes before me?
James Curran
If you're on .NET 3.5, you can kill the delegate keyword.delegate(Match match) can bematch =>
steve_c
@scalvert - to be exact, that is C# 3.0, not .NET 3.5; it would work targetting .NET 2.0 with C# 3.0, too.
Marc Gravell
A: 

Hi,

I wanted peoples perspective first how they thought to solve this so I haven't tried with anything yet.

But if you can recommend regular expressions, I try to run with it and hope it's good enough.

Thanks!

If you have any suggestions with no regular expressions (or a simple replace), I want to known that to.

A: 

Now if you have you replacements in a dictionary, like this:

 var  replacements = new Dictionary<string, string>();
 replacements["name"] = "Mike";
 replacements["age"]= "20";

then the Regex becomes quite simple:

Regex regex = new Regex(@"\{(?<key>\w+)\}");
    string formattext = "{name} is {age} years old";
 string newStr = regex.Replace(formattext, 
            match=>replacements[match.Groups[1].Captures[0].Value]);
James Curran
A: 

I haven't tested anything but to use Regular Expressions or the simple Replace method in a large string/text, which seems to be the fastest?

A: 

Try using StringTemplate. It's much more powerful than that, but it does the job flawless.

+1  A: 

How about

stringVar = "Hello, {0}. How are you doing?";
arg1 = "John";    // or args[0]
String.Format(stringVar, arg1)

You can even have multiple args, just increment the {x} and add another parameter to the Format() method. Not sure the different but both "string" and "String" have this method.

sosdude