0

I'm working on a razor page where I need to drop a series of custom fields from a variable-attribute tables. My purpose is to replace a specific pairing of symbols ('{}') with an htmlstring. To simplify however lets say i wanted to replace it with an incremental number.

This is pseudo-code for what i'm looking for.

string s = "This sample will count: {}, {}, {}."
int i = 0;
while(*string not finished*)//?
{ 
   i ++;
   s.Replace("{}", i);  
}

Output:

"This sample will count 1, 2, 3."

Is this something I need to use regex on? Any other thoughts?

EDIT

I should clarify: I am not aware of how many '{}'s until run time. The numbers may be throwing people off, I'm liking going to do something more akin to:

 s.replace("{}", stringArray[i]);
5
  • Strings are immutable in .NET. Can only transform from one string to another. Commented Jan 13, 2014 at 20:32
  • @ja72 Yes I know, but even if I swapped it into StringBuilder, which is what replace likely does behind the scenes, my question remains valid i think. The objective isn't to count, the objective it to replace each sub-string fitting the pattern with a different substring. In my actual instance the source is probably going to be strings from an array or list. If I did s.replace(1) Then the output would be "This sample will count 1, 1, 1" Commented Jan 13, 2014 at 20:36
  • 1
    So, you're trying to replicate string.Format(), but without numbers inside the braces? Commented Jan 13, 2014 at 20:42
  • There's an overload of string.Format which takes a param (you could pass your list direcrly as an array), if you could get your input with numbers in the braces it would be perfect. Commented Jan 13, 2014 at 20:43
  • @Magus That's not an unfair assessment. In my instance programmers don't get to write the strings. Users do in real time, string s is coming from a database. I was not aware of string.format(str, array). Given Pierre's comment, all I really need is to add the numbers in, which ironically makes my dummy example not so dummy. Commented Jan 13, 2014 at 21:02

4 Answers 4

3

A simple sample using Split to tokenise your input string;

string s = "This sample will count: {}, {}, {}.";
string[] tokens = s.Split(new[] { "{}"}, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();

int counter = 1;
for (int i = 0; i < tokens.Length; i++ )
{
    sb.Append(tokens[i]);
    if (i < tokens.Length - 1)
        sb.Append(counter++);
}

Console.WriteLine(sb.ToString());

Solves your posted example, but I imagine your real requirement is going to be subtly more complicated.

Sign up to request clarification or add additional context in comments.

2 Comments

This leaves out the last token. (in this case, the . at the end)
Corrected (but not tested)
2

You can use a regular expression match evaluator as follows:

var re = new Regex(@"\{\}");

string s = "This sample will count: {}, {}, {}.";

string[] replacementStrings = new string[]{"r1", "r2", "r3"};

int i = 0;

string n = re.Replace(s, m => 
    {
        return replacementStrings[i++];
    }); 

Console.WriteLine(n); // outputs: This sample will count: r1, r2, r3.

4 Comments

Thanks, though I won't have the option to hard code the number of replacement strings.
Please elaborate. The above solution is based on your EDIT regarding s.replace("{}", stringArray[i]);
Your code takes into account there are specifically three bracket pairs. Otherwise it functions quite well.
@Seth: This solution will work regardless of the value of replacementStrings. That just needs to be a parameter. It definitely does not constrain it to only 3.
1

If performance is important to you, traverse the string manually and write its contents to a StringBuilder (to prevent tons of string instance creations while concatenating and replacing strings) and then find and replace instances of the {}. string.IndexOf would be good to use for this. Once you're done, cache the result and output the string builder via StringBuilder.ToString()

Comments

0

You could do this with plain old string manupulation:

string s = "This sample will count: {}, {}, {}.";
string[] stringArray = new[] { "1", "2", "3" };
int i = 0, c = s.IndexOf("{}");
while(c >= 0)
{
    s = s.Remove(c) + stringArray[i++] + s.Substring(c + 2);  
    c = s.IndexOf("{}");
}
// s == "This sample will count: 1, 2, 3."

Or using regular expressions:

string s = "This sample will count: {}, {}, {}.";
string[] stringArray = new[] { "1", "2", "3" };
int i = 0;
s = Regex.Replace(s, "{}", m => stringArray[i++]);
// s == "This sample will count: 1, 2, 3."

Or using Linq:

string s = "This sample will count: {}, {}, {}.";
string[] stringArray = new[] { "1", "2", "3" };
s = String.Join("", s.Split(new[]{ "{}" }, StringSplitOptions.None)
                     .Select((x, i) => i < stringArray.Length ? x + stringArray[i] : x));
// s == "This sample will count: 1, 2, 3."

6 Comments

These examples will have poor performance due to the number of strings being created.
@DavidHaney Poor performance as compared to what? Do you have any proof actually that this "loss" of performance will be meaningful?
Yes, the strings will be instantiated, and thus need to be garbage collected. You'll create a lot more Gen 0 or 1, possibly 2 GC events, which will slow down your application. StringBuilder exists SOLELY to circumvent the overhead of creating string instances as by-products of operations that repeatedly manipulate them.
MSDN mentions performance issues, unfortunately without much detail, here: msdn.microsoft.com/en-us/library/ms228504.aspx
Regex.Replace(string, MatchEvaluator) method uses StringBuilder internally to build the resulting string.
|

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.