Reputation:
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
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]);
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")
Upvotes: 2
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
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