Andy Evans
Andy Evans

Reputation: 7176

Replacing each instance of a word in a string with a unique value

Within a string, I'm trying to update multiple instances of the same word with different values.

This is an overly simplified example, but given the following string:

"The first car I saw was color, the second car was color and the third car was color"

The first instance of the word color I want to replace with "red", the second instance should be "green" and the third instance should be "blue".

What I thought to try was a regex pattern to find boundried words, interate through a loop and replace them one at a time. See the example code below.

var colors = new List<string>{ "reg", "green", "blue" };
var sentence = "The first car I saw was color, the second car was color and the third car was color";

foreach(var color in colors)
{
    var regex = new Regex("(\b[color]+\b)");
    sentence = regex.Replace(sentence, color, 1);
}

However, the word "color" never gets replaced with the appropriate color name. I can't find what I've been doing wrong.

Upvotes: 6

Views: 1604

Answers (3)

mrjoltcola
mrjoltcola

Reputation: 20852

Try a match delegate.

It is an overload of Regex.Replace() that most folks miss. It simply lets you define a, potentially context sensitive, dynamic handler instead of a hardcoded string to replace with, and could have side-effects. The "i++ %" is a modulo operator is used below to simply cycle through the values. You could use a database or a hash table or anything.

var colors = new List<string> { "red", "green", "blue" };
var sentence = "The first car I saw was color, the second car was color and the third car was color";
int i = 0;
Regex.Replace(sentence, @"\bcolor\b", (m) => { return colors[i++ % colors.Count]; })

This solution works for an arbitrary number of replacements, which is more typical (global replace).

Upvotes: 4

Sven Grosen
Sven Grosen

Reputation: 5636

The problem is that in your example, color isn't always preceded and followed by a non-word character. For your example, this worked for me:

var regex = new Regex("\b?(color)\b?");

So this:

var colors = new List<string>{ "red", "green", "blue" };
var sentence = "The first car I saw was color, the second car was color and the third car was color";

foreach(var color in colors)
{
    var regex = new Regex("\b?(color)\b?");
    sentence = regex.Replace(sentence, color, 1);
}

Produces this:

The first car I saw was red, the second car was green and the third car was blue

Upvotes: 2

Steven Wexler
Steven Wexler

Reputation: 17299

I try to stay away from Regex whenever possible. It has it's place, but not for simple cases like this IMHO :)

public static class StringHelpers
{
    //Copied from http://stackoverflow.com/questions/141045/how-do-i-replace-the-first-instance-of-a-string-in-net/141076#141076
    public static string ReplaceFirst(this string text, string search, string replace)
    {
        int pos = text.IndexOf(search);
        if (pos < 0)
        {
            return text;
        }
        return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
    }
}


var colors = new List<string>{ "red", "green", "blue" };
string sentence = colors.Aggregate(
    seed: "The first car I saw was color, the second car was color and the third car was color", 
    func: (agg, color) => agg.ReplaceFirst("color", color));

Upvotes: 1

Related Questions