6

I have a peculiar problem..!

I have a string with some constant value at multiple paces. For example consider the following sting.

string tmpStr = "Hello _tmp_ how is _tmp_ this possible _tmp_ in C#...?"

Now i want to replace each of the tmp in the string with values that are stored in an array, first tmp holds array[0], second tmp holds array[1] and so on...

Any idea how this can be achieved..? I use C# 2.0

4 Answers 4

4

How about this:

string input = "Hello _tmp_ how is _tmp_ this possible _tmp_ in C#...?";
string[] array = { "value1", "value2", "value3" };

Regex rx = new Regex(@"\b_tmp_\b");

if (rx.Matches(input).Count <= array.Length)
{
    int index = 0;
    string result = rx.Replace(input, m => array[index++]);
    Console.WriteLine(result);
}

You need to ensure the number of matches found is never greater than the array's length, as demonstrated above.

EDIT: in response to the comment, this can easily work with C# 2.0 by replacing the lambda with this:

string result = rx.Replace(input, delegate(Match m) { return array[index++]; });
Sign up to request clarification or add additional context in comments.

5 Comments

Hats off to u.. exactly the same as I wanted. but how does it work? you have a lambda expression m => array[index++], how does it serve the purpose?
@Amit: the lambda or anonymous delegate take the place of the MatchEvaluator. Each match found is replaced by an element of the array. So the 1st match is replaced with array[0] then index++ will set index to 1, then the next match will be advanced to the value of array[1] and so forth.
@Ahmad: Thanks a lot.. let me explore more on the same..! I have 3.5 framework installed on my machine, the lambda expression worked fine on a project pointed to 2.0 framework..!
@Amit: Martin Booth made a very good point in his post below. The real reason for the delegate is to capture the index variable so that it can be advanced correctly for each match. Had I used array[index++] alone then it would've evaluated once and used value1 repeatedly, contrary to the goal of the question. You may want to refer to Jon Skeet's article on closures for more details: csharpindepth.com/Articles/Chapter5/Closures.aspx
@AhmadMageed, just one question. Are you sure that order of enumerating of matches in MatchEvaluator you provided will be strict left to right? In other words, what if the delegate method will invoke for second match and then for first match for example. In this hypothetical case replacement will be performed incorrectly. I understand that left to right flow is common for regex implementation, but however, what if? If you have any links that can dispel my doubts, could you provide them.
2

you can use a MatchEvaluator (a function that gets called to do do each replacement), some examples here:

http://msdn.microsoft.com/en-us/library/aa332127%28VS.71%29.aspx

Comments

1

suggestion, you can use string.Split() to split on "tmp". then iterate the list of splitted items and print them + the array values out eg pseudocode idea only

string[] myarray = new string[] { 'val1', 'val2' };
string s = "Hello _tmp_ how is _tmp_ this possible _tmp_ in C#";
string[] items = s.Split("tmp");
for (int i = 0; i < items.Length; i++)
{
    Console.WriteLine(parts[i] + myarray[i] ) ;
}

Comments

1

I would think that Ahmad Mageed's first solution is the one to go for because array[index++] is only evaluated once when passed into the rx.Replace method..

I compiled it too to verify whether I understand it correctly or not, and sure enough it produces the following output:

Hello value1 how is value1 this possible value1 in C#...?

Has the behaviour changed with the later versions of the framework? or am I mistaken in thinking that the expected output should be:

Hello value1 how is value2 this possible value3 in C#...?

2 Comments

+1 to you, excellent point. You're absolutely right, it's too late here :) My first solution works because index is a captured value. Rolling back my answer now to reflect this.
@Martin: your expectation is correct. That matches my original answer. The behavior is unchanged in the frameworks had I used array[index++] directly as I did before I rolled my answer back. That does give value1 over and over. The reason the 2nd approach worked is because the index variable is captured by the delegate. See Jon Skeet's article on Closures for more info: csharpindepth.com/Articles/Chapter5/Closures.aspx

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.