0

I have a Dictionary<string , string> dict and a string script. I want to replace each occurrence of key in script with corresponding value from the Dictionary in such a way that only tokens which are same as key are replaced.

Example

Dictionary dict has the following entries :

"name" : "John"
"age"  : "34"

and

string script = " The name and the fathersname and age and age_of_father "

Output after Replace should be :

script = " The John and the fathersname and 34 and the age_of_father " 

I have tried using string.Replace() but it doesn't work. How can I accomplish this using Regex.Replace() and concept of Lookahead ?

2 Answers 2

1

Let's match each word (\w+ the simplest pattern: word is a sequence of one or more unicode word characters) and check (with a help of the dictionary) if it should be replaced:

Dictionary<string, string> dict = 
  new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
    { "name", "John"},
    { "age", "34"}
  };

string script = " The name and the fathersname and age and age_of_father ";

//  The John and the fathersname and 34 and age_of_father 
string result = Regex.Replace(
  script,
 @"\w+",   // match each word
  match => dict.TryGetValue(match.Value, out var value) // should the word be replaced? 
    ? value          // yes, replace
    : match.Value);  // no, keep as it is
Sign up to request clarification or add additional context in comments.

6 Comments

@Tim Biegeleisen: \w+ means one ore more word (alphanumeric) characters that's why \b seems to be redundant
Hey , I wrote this regex for characters following the word $"{key}(?![_a-zA-Z0-9])" . How about characters which are preceding the word ?
@Tim Biegeleisen: no, we get fathersname match and since we don't have a corresponding key in the dict the fathersname will be kept intact
I get it +1. You are iterating the words in the sentence, and then applying the map, good idea.
@Varad: it's a very difficult question what is a word (definition). Some examples: "forget-we-not", "per cent", "i.e.", "isn't". In my answer I've put the simplest version: word is sequence of word Unicode characters (\w). If you use other rules for instance, word must start from English letter or [0-9] digit or underscope, please let us know the rules.
|
0

What does "doesn't work" mean in your question? What are you seeing? What does your code look like?

Remember that strings are immutable, and string.Replace doesn't change the original string, it returns a new string with the changes made.

For things like this (looping while doing a lot of replacements), StringBuilder.Replace is often a better choice. StringBuilder instances are mutable, so StringBuilder.Replace does its work in-place.

Do the following:

  • Initialize a StringBuilder with your script string
  • Loop through you dictionary doing replacements
  • When finished, call ToString on the StringBuilder to get the result

I wish there was a way to get StringBuilder and Regex to work together.

2 Comments

Hi, I know that strings are immutable. The point of the question is that I want to replace only those words which are identifiers and not substrings of identifiers. For Eg : "age" should be replaced but not "age_of_father". For that, Regex will be required.
The traditional way to do this is to make your replaceable tokens explicitly and easily identifiable as tokens, for example $(age). With that, you can run through a list of token name value/pairs, glue the $() to the token name and just use StringBuilder.Replace. Otherwise, you end up fighting word boundaries. For example, working properly with both "He's at that rebellious age." And "He's at the age.of.rebellion"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.