tags:

views:

81

answers:

4

Hi, 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

+2  A: 

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

jspcal
+1  A: 

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] ) ;
}
ghostdog74
+3  A: 

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++]; });
Ahmad Mageed
This will not work on C# 2.0.
Kobi
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
@Kobi: easily solved, see update.
Ahmad Mageed
@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 Mageed
@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
@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: http://csharpindepth.com/Articles/Chapter5/Closures.aspx
Ahmad Mageed
+1  A: 

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#...?

Martin Booth
+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.
Ahmad Mageed
@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: http://csharpindepth.com/Articles/Chapter5/Closures.aspx
Ahmad Mageed