Replace Variables in String? - c#

I am Searching though the contents of a Excel Spreadsheet template at replacing all the variables represented by #Something.
I have all the variables names come up with code, i'm just looking for a way to replace the them in a string.
Example:
My name is #Name
I want it to become:
My name is John.
My Code explained:
I have an array holding a struct which holds:
TagPointer: this is my variable #name,
TagValue: this would be the name John
Here i can get the index of where my variable is and i have the original String its Comp.
I am just unsure how i can replace the #Something.
int testnum;
if (Comp != "null")
{
if (Comp.IndexOf(ArrayNode[i].TagPointer) != -1)
{
testnum = Comp.IndexOf(ArrayNode[i].TagPointer);
}
}

use string.Format(), string.Replace() there is less convenient
string value = "John";
string result = string.Format("My name is {0}", value);

Unless I'm missing something, can't you use the string.replace function?
You could do something like:
foreach (var tag in ArrayNode)
{
Comp = Comp.Replace(tag.TagPointer, tag.TagValue);
}

Have you ever seen the FormatWith extension?
With it you can write something like this:
Status.Text = "{UserName} last logged in at {LastLoginDate}".FormatWith(user);

Why not using
ie
string name = "Giusepe";
string _tmp = "My name is #Name";
_tmp = _tmp.Replace("#Name", name);

You could iterate over your array and use the .Contains() to see which tag you have present and use the .Replace() to replace the tag with the actual value.

Do you want this:
string a = "#Something";
a = a.Replace("#somethig", Value);
?

Years later, we now have string interpolation to help with this.

Related

C# How to treat a string variable as interpolated string?

the interpolated string is easy, just a string lead with $ sign. But what if the string template is coming from outside of your code. For example assume you have a XML file containing following line:
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv"/>
Then you can use LINQ to XML read the content of the attributes in.
//assume the ele is the node <filePath></filePath>
string pathFrom = ele.Attribute("from").value;
string pathTo = ele.Attibute("to").value;
string date = DateTime.Today.ToString("MMddyyyy");
Now how can I inject the date into the pathFrom variable and pathTo variable?
If I have the control of the string itself, things are easy. I can just do var xxx=$"C:\data\settle{date}.csv";But now, what I have is only the variable that I know contains the placeholder date
String interpolation is a compiler feature, so it cannot be used at runtime. This should be clear from the fact that the names of the variables in the scope will in general not be availabe at runtime.
So you will have to roll your own replacement mechanism. It depends on your exact requirements what is best here.
If you only have one (or very few replacements), just do
output = input.Replace("{date}", date);
If the possible replacements are a long list, it might be better to use
output = Regex.Replace(input, #"\{\w+?\}",
match => GetValue(match.Value));
with
string GetValue(string variable)
{
switch (variable)
{
case "{date}":
return DateTime.Today.ToString("MMddyyyy");
default:
return "";
}
}
If you can get an IDictionary<string, string> mapping variable names to values you may simplify this to
output = Regex.Replace(input, #"\{\w+?\}",
match => replacements[match.Value.Substring(1, match.Value.Length-2)]);
You can't directly; the compiler turns your:
string world = "world";
var hw = $"Hello {world}"
Into something like:
string world = "world";
var hw = string.Format("Hello {0}", world);
(It chooses concat, format or formattablestring depending on the situation)
You could engage in a similar process yourself, by replacing "{date" with "{0" and putting the date as the second argument to a string format, etc.
SOLUTION 1:
If you have the ability to change something on xml template change {date} to {0}.
<filePath from="C:\data\settle{0}.csv" to="D:\data\settle{0}.csv" />
Then you can set the value of that like this.
var elementString = string.Format(element.ToString(), DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
SOLUTION 2:
If you can't change the xml template, then this might be my personal course to go.
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv" />
Set the placeholder like this.
element.Attribute("to").Value = element.Attribute("to").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
element.Attribute("from").Value = element.Attribute("from").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
I hope it helps. Kind regards.
If you treat your original string as a user-input string (or anything that is not processed by the compiler to replace the placeholder, then the question is simple - just use String.Replace() to replace the placehoder {date}, with the value of the date as you wish. Now the followup question is: are you sure that the compiler is not substituting it during compile time, and leaving it untouched for handling at the runtime?
String interpolation allows the developer to combine variables and text to form a string.
Example
Two int variables are created: foo and bar.
int foo = 34;
int bar = 42;
string resultString = $"The foo is {foo}, and the bar is {bar}.";
Console.WriteLine(resultString);
Output:
The foo is 34, and the bar is 42.

How do i split a value in model class

How do i split a value in model class.
in list[0].key = 1 and list[0].value = 1_5
here is the code:
if (data.Things.Count != 0)
{
var ans = new List<QuestionModel>();
ans = data.Things.Select(item =>
{
return new QuestionModel()
{
QuestionId = Convert.ToInt32(item.Key),
AnswerId = Convert.ToInt32(item.Value),
};
}).ToList();
}
here i want to split the value.i.e. in AnswerId want only 5.
If you always want the part after the underscore, and it's always an underscore in the format of item.Value, you can do this:
item.Value.Split('_')[1];
This splits the string on the _ and then takes the second part (e.g. what is after the _).
So the complete line of code would be:
AnswerId = Convert.ToInt32(item.Value.Split('_')[1]),
I would add that the fact you are having to do something this clunky is perhaps a symptom of your model not being a good fit to your domain - if you are able to refactor your model such that you don't have to do this and the field in question contains only the data you are interested in then your solution would be cleaner and more easily maintainable.
Come on. Value is a string value right? Did you look at string class what methods does it have? There is a method called split. Read more here: https://msdn.microsoft.com/en-US/library/b873y76a(v=vs.110).aspx
In short:
string value = "1_5";
string[] arr = value.Split('_');
//now arr[0] is "1" and arr[1] is "5"
int i = Convert.ToInt(arr[1]);
I'm not entirely sure, what you're trying to achieve, but I think you want to split the string "1_5" and retrieve just the "5". This can be achieved using string.Split():
(item.Value.Split('_'))[1]

Substring continue to search until specific character

I am getting a string at the run time. The string is in JSON format( key value pair). One of the key is "userId". I need to retrieve the value of userId. The problem is I don't know the position of "userId" key. The string can look like {"name":"XX", "userId":"YYY","age":"10"} or it can look like {"age":"10", "name":"XX", "userId":"YYY"} or it can look like this {"age":"10"}
I am thinking of using substring()
var index = myString.IndexOf("userId\":\"");
if(index != -1){
myString.Subtring(index, ???)//How to specify the length here
}
I am not sure, how to say continue until you find next " (double quote)
If only userId attribute is planned to use, you can simply declare an object with userId member and deserialize json. any other attributes will be omitted during deserialization.
class UserIDObj
{
public string UserId { get; set; }
}
var obj = JsonConvert.DeserializeObject<UserIDObj>("{\"name\":\"XX\", \"userId\":\"YYY\",\"age\":\"10\"}");
string usrID = obj.UserId;
Answer given by #Wiktor Stribiżew also works like a charm. I am pasting his solution.
System.Text.RegularExpressions.Regex.Match(myString, "\"userId\":\"([^\"]+)").Groups[1].Value
You could do this:
var needle = "\"userId\":"; // also you forgot to escape the quote here
var index = myString.IndexOf(needle);
if(index != -1){
var afterTheUserId = myString.Substring(index + needle.Length);
var quoteIndex = afterTheUserId.IndexOf('"');
// do what you want with quoteIndex
}
But as Eric Philips and PhonicUK said, you should use a proper JSON parser instead of writing your own string functions.

How to get text until a symbol in string

How to get text before a symbol in string ? Any ideas?
e.g. acsbkjb/123kbvh/123jh/
get text before first - "/"
Try this
string ss = myString.Split('/')[0];
You can use Substring() method to get the required part of the string.
String text="acsbkjb/123kbvh/123jh/";
int index=text.IndexOf('/');
String text2="";
if(index>=0)
text2=text.Substring(0,index);
get substring like
youstring.Substring(0,yourstring.IndexOf('/'));
The IEnumerable approach
string str = "acsbkjb/123kbvh/123jh/";
var result = new string(str.TakeWhile(a => a != '/').ToArray());
Console.WriteLine(result);
If there are no forward slashes this works without need to check the return of IndexOf
EDIT Keep this answer just as an example because the efficiency of this approach is really worse. IndexOf works faster also if you add an if statement to check the return value.
string text = "acsbkjb/123kbvh/123jh/";
string text2 = text.Substring(0, text.IndexOf("/"));

Is it possible to include a C# variable in a string variable without using a concatenator?

Does .NET 3.5 C# allow us to include a variable within a string variable without having to use the + concatenator (or string.Format(), for that matter).
For example (In the pseudo, I'm using a $ symbol to specify the variable):
DateTime d = DateTime.Now;
string s = "The date is $d";
Console.WriteLine(s);
Output:
The date is 4/12/2011 11:56:39 AM
Edit
Due to the handful of responses that suggested string.Format(), I can only assume that my original post wasn't clear when I mentioned "...(or string.Format(), for that matter)". To be clear, I'm well aware of the string.Format() method. However, in my specific project that I'm working on, string.Format() doesn't help me (it's actually worse than the + concatenator).
Also, I'm inferring that most/all of you are wondering what the motive behind my question is (I suppose I'd feel the same way if I read my question as is).
If you are one of the curious, here's the short of it:
I'm creating a web app running on a Windows CE device. Due to how the web server works, I create the entire web page content (css, js, html, etc) within a string variable. For example, my .cs managed code might have something like this:
string GetPageData()
{
string title = "Hello";
DateTime date = DateTime.Now;
string html = #"
<!DOCTYPE html PUBLIC ...>
<html>
<head>
<title>$title</title>
</head>
<body>
<div>Hello StackO</div>
<div>The date is $date</div>
</body>
</html>
";
}
As you can see, having the ability to specify a variable without the need to concatenate, makes things a bit easier - especially when the content increases in size.
No, unfortunately C# is not PHP.
On the bright side though, C# is not PHP.
Almost, with a small extension method.
static class StringExtensions
{
public static string PHPIt<T>(this string s, T values, string prefix = "$")
{
var sb = new StringBuilder(s);
foreach(var p in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
sb = sb.Replace(prefix + p.Name, p.GetValue(values, null).ToString());
}
return sb.ToString();
}
}
And now we can write:
string foo = "Bar";
int cool = 2;
var result = "This is a string $foo with $cool variables"
.PHPIt(new {
foo,
cool
});
//result == "This is a string Bar with 2 variables"
No, it doesn't. There are ways around this, but they defeat the purpose. Easiest thing for your example is
Console.WriteLine("The date is {0}", DateTime.Now);
string output = "the date is $d and time is $t";
output = output.Replace("$t", t).Replace("$d", d); //and so on
Based on the great answer of #JesperPalm I found another interesting solution which let's you use a similar syntax like in the normal string.Format method:
public static class StringExtensions
{
public static string Replace<T>(this string text, T values)
{
var sb = new StringBuilder(text);
var properties = typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToArray();
var args = properties
.Select(p => p.GetValue(values, null))
.ToArray();
for (var i = 0; i < properties.Length; i++)
{
var oldValue = string.Format("{{{0}", properties[i].Name);
var newValue = string.Format("{{{0}", i);
sb.Replace(oldValue, newValue);
}
var format = sb.ToString();
return string.Format(format, args);
}
}
This gives you the possibility to add the usual formatting:
var hello = "Good morning";
var world = "Mr. Doe";
var s = "{hello} {world}! It is {Now:HH:mm}."
.Replace(new { hello, world, DateTime.Now });
Console.WriteLine(s); // -> Good morning Mr. Doe! It is 13:54.
The short and simple answer is: No!
string.Format("The date is {0}", DateTime.Now.ToString())
No, But you can create an extension method on the string instance to make the typing shorter.
string s = "The date is {0}".Format(d);
string.Format (and similar formatting functions such as StringBuilder.AppendFormat) are the best way to do this in terms of flexibility, coding practice, and (usually) performance:
string s = string.Format("The date is {0}", d);
You can also specify the display format of your DateTime, as well as inserting more than one object into the string. Check out MSDN's page on the string.Format method.
Certain types also have overloads to their ToString methods which allow you to specify a format string. You could also create an extension method for string that allows you to specify a format and/or parse syntax like this.
How about using the T4 templating engine?
http://visualstudiomagazine.com/articles/2009/05/01/visual-studios-t4-code-generation.aspx
If you are just trying to avoid concatenation of immutable strings, what you're looking for is StringBuilder.
Usage:
string parameterName = "Example";
int parameterValue = 1;
Stringbuilder builder = new StringBuilder();
builder.Append("The output parameter ");
builder.Append(parameterName);
builder.Append("'s value is ");
builder.Append(parameterValue.ToString());
string totalExample = builder.ToString();
Since C# 6.0 you can write string "The title is \{title}" which does exactly what you need.
you can use something like this as mentioned in C# documentation.
string interpolation
string name = "Horace";
int age = 34;
Console.WriteLine($"He asked, \"Is your name {name}?\", but didn't wait for a reply :-{{");
Console.WriteLine($"{name} is {age} year{(age == 1 ? "" : "s")} old.");
Or combined:
Console.WriteLine("The date is {0}", DateTime.Now);
Extra info (in response to BrandonZeider):
Yep, it is kind-a important for people to realize that string conversion is automatically done. Manually adding ToString is broken, e.g.:
string value = null;
Console.WriteLine("The value is '{0}'", value); // OK
Console.WriteLine("The value is '{0}'", value.ToString()); // FAILURE
Also, this becomes a lot less trivial once you realize that the stringification is not equivalent to using .ToString(). You can have format specifiers, and even custom format format providers... It is interesting enough to teach people to leverage String.Format instead of doing it manually.

Categories