I would recommend a few changes to your code. First, move the regular expression definition out of the method and use the RegexOptions.Compiled
option to reduce the setup time per call. Also, move creation of the random number generator out of the heavily used method.
Also, you can eliminate much unnecessary string searching by telling the regular expression where to start matching. This is important if you end up doing many iterations of the loop. The idea is that if you've already done the replacements up to position M in the string, there's no reason to check those for matches because there won't be any.
You can eliminate the calls to TrimStart
and TrimEnd
by replacing the expression with:
String[] parts = m.Value.Substring(1, m.Value.Length-2).Split('|');
You already know that the string starts with {
and ends with }
, and doesn't have either of those two characters anywhere in the middle, so all you have to do is chop off the first and last characters. There's no reason to incur the cost of the temporary strings created by TrimStart
and TrimEnd
.
Another possibility would be to add a capture group to the regular expression (placing parentheses around the part you want to capture), and operating on the captured text rather than the entire matched expression.
Putting all those suggestiong together leads to:
static Regex reg = new Regex(@"\{([^\{\}]*)\}", RegexOptions.Compiled);
static Random rand = new Random();
public static String Spin(String text)
{
int matchPos = 0;
while (true)
{
Match m = reg.Match(text, matchPos);
if (!m.Success) break;
String[] parts = m.Groups[1].Value.Split('|');
int i = rand.Next(parts.Length);
text = text.Substring(0, m.Index) + parts[i] + text.Substring(m.Index + m.Length);
matchPos = m.Index;
}
return text;
}
That said, this won't support nesting, and making a regex solution that does support nesting is likely to be somewhat difficult. It's also less than optimum in terms of speed because it spends a lot of time building and rebuilding the text
string. With a little thought, you can optimize it a bit more, but it will never be as fast as an optimized custom parser solution like SergyS supplied.
If speed is paramount, then you'll want a custom parser. The regex version won't be as fast, but if it's fast enough it has the benefit of being smaller, and easier to understand and modify than a custom parser.