RRM
RRM

Reputation: 3451

Replace several substrings in a string

I need to replace several substrings in a string

Let's say:

so for example "AB gives BD"

The "naive" approach doesn't work properly:

string S="AB";
S=S.Replace("A","B");
S=S.Replace("B","D");

as it will give DD instead of BD. (first A is changed to B but then is unnecessarily changed to D)

How to deal with such cases? Does it make sense with substrings of any size to do such a separate replacements?

EDIT: I gave some not real life example where in fact it would work doing it in reverse order(first B to D, then A to B) But as others noticed I'm interested in more general solutions: for any list of char substitutions and for any list of words substitutions

With chars I suppose now a good approach is just to go through all chars in a string and build a new string making replacements when necessary.

For words I suppose it could be more difficult, what if one replaced word is a part of another word?

For example

string S="man superman woman superwoman"

and I want replace "man" to "boy" and "woman" to "girl" only as single words

Upvotes: 1

Views: 497

Answers (5)

Omri Aharon
Omri Aharon

Reputation: 17064

Assuming there are no cycles, you need to do it the other way around. Meaning:

string S="AB";
S=S.Replace("B","D");
S=S.Replace("A","B");

This way, B switches to D, then A switches to B and you have no unwanted changes.

As Niklas B. rightfully pointed out, in case of general substrings there's a different way that probably should be taken.

I would iterate over the string, storing the indexes where any of the substrings appear. Once done, then I'll go ahead and perform the actual switching. This way you cannot "run over" changes that you made.

Upvotes: 5

Mzf
Mzf

Reputation: 5260

Use Regex.Replace

Like the below code, you can map the strings that you want to replace with their replacement. This is more clean and for some - more readable

IDictionary<string,string> map = new Dictionary<string,string>()
        {
           {"A","B"},
           {"B","D"},
        };
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);

Upvotes: 0

Abe
Abe

Reputation: 117

Just change order of code lines:

string S="AB";
S=S.Replace("B","D");
S=S.Replace("A","B");

Upvotes: -1

Blam
Blam

Reputation: 2965

One simple way is to simply loop through the string yourself, and then using an if-else or switch statement to test the characters and change them accordingly.

This way characters only change once.

var testString = "Hello World";
var newString = new StringBuilder();

foreach (char c in testString)
{
    switch (c)
    {
        case 'e':
            newString.Append('l');
            break;
        case 'l':
            newString.Append('e');
            break;
        default:
            newString.Append(c);
            break;
    }
}

// testString will be "Hleeo Wored"
testString = newString.ToString();

Upvotes: 3

Pieter
Pieter

Reputation: 201

You could first replace "A" with a token that certainly will not occur in the source string.

For example:

S=S.Replace("A","#");
S=S.Replace("B","D");
S=S.Replace("#","B");

Upvotes: 2

Related Questions