Replace List of string into an existing string C#?

130 Views Asked by At

I Have a class and inside this class a string variable. I want to replace all the occurrences of specific words inside this variable with the List<string> of string.

using System;
using System.Collections.Generic;
public class HelloWorld
{
    List<string> lst = new List<string>();
    lst.Add("Sunil");
    lst.Add("Sunil123");
    lst.Add("Sunil@123");
    string smsTemplate = "Dear {#var#},You have successfully register to online system please login to system by below credentials,User Name : {#var#}   Password : {#var#}  SunSoft, DeshlahreMiniGraden";
    string searchStr = "{#var#}";
}

So the output of this "smsTemplate" variable should be replaced with the list of strings provided. For example "Sunil" should be placed at the position of first "{#var#}","Sunil123" should be replaced at the position of second "{#var#}" and so on.

7

There are 7 best solutions below

0
Astrid E. On BEST ANSWER

You could do it in a quite straight-forward manner by splitting the smsTemplate on the searchStr and building a new string by appending the split parts from smsTemplate and each item in lst in an alternating manner. For instance:

List<string> lst = new List<string>();

lst.Add("Sunil");
lst.Add("Sunil123");
lst.Add("Sunil@123");

string smsTemplate = "Dear {#var#},You have successfully register to online system please login to system by below credentials,User Name : {#var#}   Password : {#var#}  SunSoft, DeshlahreMiniGraden";
string searchStr = "{#var#}";

var templateParts = smsTemplate.Split(searchStr);

// In case the {#var#} count in smsTemplate differs from the lst count
var replacementCount = Math.Min(lst.Count, templateParts.Length - 1);

var builder = new StringBuilder(templateParts[0]);

for (var i = 0; i < replacementCount; i++)
{
    builder.Append(lst[i]);
    builder.Append(templateParts[i + 1]);
}

var sms = builder.ToString();

A fiddle is found here.

1
timiking5 On

It is an expensive operation in terms of memory, which will result in low perfomace. The best way to approach it, is to be certain with what SMS templates you have. Please checkout my solution for your problem:

public class Solution
{
    public string SmsTemplate1(string[] args)
    {
        return string.Format("Hello, {0}. Your new passowrd is {1}", args[0], args[1]);
    }
    public string SmsTemplate2(string[] args)
    {
        return string.Format("Hello, {0}. Here are you accout details:\nNew login: {1}\nNew password: {2}", args[0], args[1], args[2]);
    }
}
3
DavidG On

You could do something like this, this will replace each string one by one, but only the first occurence:

private string SequenceReplace(string template, string search,
    IEnumerable<string> replacements)
{
    var output = template;
    
    foreach (var replacement in replacements)
    {
        int position = output.IndexOf(search);
        if (position >= 0)
        {
            output = output.Substring(0, position) + 
                     replacement + 
                     output.Substring(position + search.Length);
        }
    }
    
    return output;
}

And use it like this:

List<string> lst = new List<string>();
lst.Add("Sunil");
lst.Add("Sunil123");
lst.Add("Sunil@123");
string smsTemplate = "<snipped>";

var result = SequenceReplace(smsTemplate, searchStr, last);
1
Daniel Parra On

Why not use a Dictionary instead? Anyway, I'd recommend you modify the string to be replaced from

string smsTemplate = "Dear {#var#},You have successfully register to online system please login to system by below credentials,User Name : {#var#}   Password : {#var#}  SunSoft, DeshlahreMiniGraden";

To

string smsTemplate = "Dear {0},You have successfully register to online system please login to system by below credentials,User Name : {1}   Password : {2}  SunSoft, DeshlahreMiniGraden";

If your list of strings always has the same order (username first (index 0), then password (1), then email (2)) you can simply do:

string.Format(smsTemplate, lst.ElementAt(2), lst.ElementAt(0), lst.ElementAt(1));

An easier way would be to use a Dictionary. Something like:

Dictionary<string, string> lst = new Dictionary<string, string>();
lst.Add("username","Sunil");
lst.Add("password", "Sunil123");
last.Add("email", "Sunil@123");

Then with the above changes in the string you can simply do:

string.Format(smsTemplate, lst["email"], lst["username"], lst.["password"]);

Hope this helps.

3
Dmitry Bychenko On

There is solution with IndexOf, let me provide direct Regex.Replace:

using System.Text.RegularExpressions;

...

int count = 0;

var result = Regex.Replace(smsTemplate, Regex.Escape(searchStr), match => lst[count++]);

Here we search for searchStr - note Regex.Escape to escape all regex symbols like { and for each match we get its substitute

Fiddle

A better way is to use Dictionary, not List:

Dictionary<string, string> dict = new Dictionary<string, string>() {
  { "name",     "Sunil"},
  { "mail",     "[email protected]"},
  { "password", "SunilSecret"},
}

And then

string smsTemplate = "Dear {#mail#},You have successfully register to online system please login to system by below credentials,User Name : {#name#}   Password : {#password#}  SunSoft, DeshlahreMiniGraden";

var result = Regex.Replace(
    smsTemplate, 
  @"\{#\p{L}+#\}", 
    match => dict.TryGetValue(match.Value.Trim('{', '}', '#'), out  var value) 
      ? value 
      : match.Value);
0
Rufus L On

You can use String.Split to split the input string on the replace string, Enumerable.Zip to merge the resulting array with the list of replacement strings, and String.Concat to combine the parts back to a new string:

private static string SequenceReplace(string input, string replace, 
    IEnumerable<string> replacements)
{
    return string.Concat(input.Split(replace).Zip(replacements)
        .Select(s => $"{s.Item1}{s.Item2}"));
}
0
Panagiotis Kanavos On

I'd try to use an existing template library instead of implementing another one. Popular libraries are mature, performant and tested by multiple developers over the years. You'll be able to find docs, ready-made templates or guides for many popular scenarios.

One option, that's very close to what you described, is Handebars.net, a .NET implementation of the popular Handlebars template engine. This allows you to create and compile the template once, then reuse it to generate text:

var source = @"
Dear {{user}}},
You have successfully register to online system please login to system by below credentials

User Name : {{name}}
Password : {{pass}}

SunSoft, DeshlahreMiniGraden";

var template = Handlebars.Compile(source);

The template can be used either with dictionaries, strongly-typed or dynamic objects eg :

var data = new {
    user = "...",
    name = "...",
    pass = "...."
};

var result = template(data);

or

var data = new Dictionary<string,object>{
    ["user"] = "...",
    ["name"] = "...",
    ["pass"] = "...."
};

var result = template(data);