user3310334
user3310334

Reputation:

C# do many replacements at once in a String

I have a dictionary of replacements

var substitutions = new Dictionary<string, string>()
{
    { "one", "two" },
    { "two", "three" },
};

I want to turn the string "one two three four" into "two three three four".

Running any kind of iterative replacement chain like

var phrase = "one two three four";
substitutions.Aggregate(phrase, (current, substitution) => current.Replace(substitution.Key, substitution.Value)));

or

var sb = new StringBuilder(phrase);
foreach (var entry in substitutions)
{
    sb.Replace(entry.Key, entry.Value);
}
sb.ToString();

yields "three three three four" because the second replacement "two" → "three" is able to see the "one" → "two" output from the previous output.

How can I only replace "original" words?

Upvotes: 3

Views: 116

Answers (3)

Johnathan Barclay
Johnathan Barclay

Reputation: 20372

You could use regex as follows:

var substitutions = new Dictionary<string, string>()
{
    { "one", "two" },
    { "two", "three" },
};

var phrase = "one two three four";

var pattern = string.Join("|", substitutions.Keys.Select(Regex.Escape));

// Pattern is: one|two

var result = Regex.Replace(phrase, pattern, match => substitutions[match.Value]);

Working example


If the substitutions must only match complete words, you can update pattern to include word boundaries \b:

substitutions.Keys.Select(x => @$"\b{Regex.Escape(x)}\b")

Working example

Upvotes: 2

Mathias R. Jessen
Mathias R. Jessen

Reputation: 175085

Split the string into individual terms, now you can iterate just once and replace:

var phrase = "one two three four";
var terms = phrase.Split();

for(int i = 0; i < terms.Length; i++)
{
  if(substitutions.ContainsKey(terms[i]))
  {
    terms[i] = substitutions[terms[i]];
  }
}

phrase = string.Join(" ", terms);

Upvotes: 2

Franck
Franck

Reputation: 4440

Since it's always single words split by space just split the string and loop through that collection to rebuild the new result

var substitutions = new Dictionary<string, string>()
{
    { "one", "two" },
    { "two", "three" },
};
var phrase = "one two three four";

// convert to list of words
var words = phrase.Split(new[] { " " }, StringSplitOptions.None).ToList();

// keep the transformed result
var result = new StringBuilder();

// for each words
foreach (var word in words)
{
    // add a space before since we removed it.
    // will trim later on for the first useless space it creates
    result.Append(" ");

    // to get the dictionary value
    string substitutionWord;

    // if we found the dictionary key
    if (substitutions.TryGetValue(word, out substitutionWord))
    {
        // add substitution word instead
        result.Append(substitutionWord);
    }
    else // not found
    {
        // keep the original word
        result.Append(word);
    }
}

var finalResult = result.ToString().Trim();

Upvotes: 1

Related Questions