I have a string
string str ="Enter {0} patient name";
I am using string.format to format it.
String.Format(str, "Hello");
Now if i want patient also to be retrieved from some config then I need to change str to something like
"Enter {0} {1} name". So it will replace the {1} with second value. The problem is that I want instead of {1} some other format something like {pat}. But when I try to use, it throws an error. The reason I want a different format is that there are lot of files I need to change like this(which may contain {0},{1} etc). So I need a custom placeholder which can be replaced at run-time.
You might want to check out FormatWith 2.0 by James Newton-King. It allows you to use property names as formatting tokens such as this:
var user = new User()
{
Name = "Olle Wobbla",
Age = 25
};
Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));
You can also use it with anonymous types.
UPDATE: There is also a similar solution by Scott Hanselman but it is implemented as a set of extension methods on Object instead of String.
UPDATE 2012: You can get Calrius Consulting's NETFx String.FormatWith Extension Method NuGet package on NuGet.org
UPDATE 2014: There is also StringFormat.NET and littlebit's StringFormat
Regex with a MatchEvaluator seems a good option:
static readonly Regex re = new Regex(#"\{([^\}]+)\}", RegexOptions.Compiled);
static void Main()
{
string input = "this {foo} is now {bar}.";
StringDictionary fields = new StringDictionary();
fields.Add("foo", "code");
fields.Add("bar", "working");
string output = re.Replace(input, delegate (Match match) {
return fields[match.Groups[1].Value];
});
Console.WriteLine(output); // "this code is now working."
}
object[] myInts = new int[] {8,9};
However you can get away with:
object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);
I saw all the answers above, yet, couldn't get the question right :)
Is there any particular reason why the following code does not meet your requirement?
string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();
string result = "Enter " + myFirstStr + " " + mySecondStr + " name";
Here's another version of this that I found here: http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1
Any solution to this is going to involve reflection, which is less than ideal, but here's his code with some of the other major performance issues resolved. (No error checking. Add it if you like.):
1) Uses direct runtime reflection, no DataBinder overhead
2) Doesn't use regular expressions, uses a single-pass parse and state.
3) Doesn't convert the string into an intermediate string and then convert it again to the final format.
4) Allocates and concatenates with a single StringBuilder instead of newing up strings all over the place and concatenating them into new strings.
5) Removes the stack overhead of calling a delegate for n replace operations.
6) In general is a single pass through that will scale in a relatively linear manner (still some cost for each prop lookup and nested prop lookup, but that's that.)
public static string FormatWith(this string format, object source)
{
StringBuilder sbResult = new StringBuilder(format.Length);
StringBuilder sbCurrentTerm = new StringBuilder();
char[] formatChars = format.ToCharArray();
bool inTerm = false;
object currentPropValue = source;
for (int i = 0; i < format.Length; i++)
{
if (formatChars[i] == '{')
inTerm = true;
else if (formatChars[i] == '}')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
sbCurrentTerm.Clear();
inTerm = false;
currentPropValue = source;
}
else if (inTerm)
{
if (formatChars[i] == '.')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
currentPropValue = pi.GetValue(source, null);
sbCurrentTerm.Clear();
}
else
sbCurrentTerm.Append(formatChars[i]);
}
else
sbResult.Append(formatChars[i]);
}
return sbResult.ToString();
}
You can also use the example from Marc Gravell and Extend the String class object:
public static class StringExtension
{
static readonly Regex re = new Regex(#"\{([^\}]+)\}", RegexOptions.Compiled);
public static string FormatPlaceholder(this string str, Dictionary<string, string> fields)
{
if (fields == null)
return str;
return re.Replace(str, delegate(Match match)
{
return fields[match.Groups[1].Value];
});
}
}
Example usage:
String str = "I bought a {color} car";
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("color", "blue");
str.FormatPlaceholder(fields));
You are probably better off using Replace for the custom field and Format for the rest, like:
string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");
var user = new User()
{
Name = "John",
Age = 21
};
String result = $"Your name is {user.Name} and your age is {user.Age}";
I wanted something that worked more like Python's string formatting, so I wrote this:
https://gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b
Use it like this:
Dim template = New FormatFromDictionary("{cat} vs {dog}")
Dim d = New Dictionary(Of String, Object) From {
{"cat", "Felix"}, {"dog", "Rex"}}
Console.WriteLine(template.Replace(d)) ' Felix vs Rex
Related
I am trying to append two StringBuilders so that they produce something like:
Device # 1 2 3
Pt.Name ABC DEF GHI
what I have tried is:
class Program
{
class Device
{
public int ID { get; set; }
public string PatName { get; set; }
}
static void Main(string[] args)
{
var datas = new List<Device>
{
new Device { ID = 1, PatName = "ABC" },
new Device { ID = 2, PatName = "DEF" },
new Device { ID = 3, PatName = "GHO" }
};
// there is a collection which has all this information
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0} {1}", "Device #", "Pt.Name").AppendLine();
foreach (var data in datas)
{
var deviceId = data.ID;
var patName = data.PatName;
sb.AppendFormat("{0} {1}", deviceId, patName).AppendLine();
}
Console.WriteLine(sb);
}
}
but it is printing it in vertical manner, like
Device # Pt.Name
1 ABC
2 DEF
3 GHI
and if I remove that last AppendLine(); it is appending it at the end in the same line.
I want to use only one stringbuilder followed by only one foreach loop.
1.You could do it like:
StringBuilder sb=new StringBuilder();
sb.Append("Device #");
foreach(var data in datas)
sb.Append($" {data.deviceId}");
sb.Append("PT.Name");
foreach(var data in datas)
sb.Append($" {data.PatName}");
2.if you want to loop only once then you can use 2 StringBuilders:
StringBuilder sb1=new StringBuilder();
StringBuilder sb2=new StringBuilder();
sb1.Append("Device #");
sb2.Append("Pt.Name");
foreach(var data in datas)
{
sb1.Append($" {data.deviceId}");
sb2.Append($" {data.patName}");
}
sb1.Append(sb2.ToString());
3.You could also use string.Join() which also relies on StringBuilder to write a one-liner but however this way you have extra select statements:
string result = $"Device # {string.Join(" ",datas.Select(x => x.deviceId))}\r\nPt.Name {string.Join(" ",datas.Select(x => x.patName))}";
I love your question because it is based on avoiding these two assumption, 1) that strings are always printed left to right and 2) newlines always result in advancing the point of printing downwards.[1]
Others have given answers that will probably meet your needs, but I wanted to write about why your way of thinking won’t work. The assumptions above are so engrained into people’s thinking about how strings and terminals work that I'm sure many people taught your question was odd or even naïve, I did at first.
StringBuilder doesn’t print strings to the screen. Somewhere I suspect you are calling Console.Write to print the string. StringBuilder allows you to convert non-string variables as strings and to concatenate strings together in a more efficient way than String.Format and the + operator, see Immutability and the StringBuilder class.
When you are done using StringBuilder what you have is a string of characters. It’s called a string because it is a 1D structure, one character after each other. There is nothing special about the new line characters in the string,[2] they are just characters in the list. There is nothing in the string that specifies the position the characters other that that each one comes after the previous one. When you do something like Console.Write the position of the character on the screen is defined by the implementation of that method, or the implements of the terminal, or both. They follow the conventions of our language, i.e. each character is to the right of the previous one. When Console.Write you encounters a newline it then prints the following character in the first position of the line below the current one.
If you are using String, StringBuilder and Console you can write code to create a single string with the pieces of test in the places you want so that when Console.Write follows the left to write, top to bottom conventions your text will appear correctly. This is what the other answers here do.
Alternately you could find a library which gives you more control over when text is printed on the screen. These were very popular before Graphical User Interfaces when people build interactive applications in text terminals. Two examples I remember are CRT for Pascal and Ncurses for C. If you want to investigate this approach I’d suggest doing some web searches or even another question here. Most terminal applications you see at banks, hospitals and airlines use such a library running on a VAX.
[1] This may be differently in systems setup for languages which are not like English, or not like Latin.
[2] The character or characters which reprsent a new line are different on different operating systems.
normally you cannot horizontally append to the right side of stringbuilder so maybe you roll your own extension method such as
static class SbExtensions
{
public static StringBuilder AppendRight(this StringBuilder sb, string key, string value)
{
string output = sb.ToString();
string[] splitted = output.Split("\n");
splitted[0] += key.PadRight(10, ' ');
splitted[1] += value.PadRight(10, ' ');
output = string.Join('\n', splitted);
return new StringBuilder(output);
}
}
simple solution:
StringBuilder sb2 = new StringBuilder(columns);
foreach(var data in datas)
{
sb2 = sb.AppendRight(data.ID.ToString(), data.PatName);
}
Console.WriteLine(sb.ToString());
Console.ReadLine();
complex one: dynamic
just another solution using MathNet.Numerics library at https://numerics.mathdotnet.com/
introduce an array property in your Entity class
class Device
{
public int ID { get; set; }
public string PatName { get; set; }
public string[] Array
{
get
{
return new string[] { ID.ToString(), PatName };
}
}
}
then in main method
static void Main(string[] args)
{
var datas = new List<Device>
{
new Device { ID = 1, PatName = "ABC" },
new Device { ID = 2, PatName = "DEF" },
new Device { ID = 3, PatName = "GHO" }
};
var MatrixValues = datas
.SelectMany(x => x.Array)
.Select((item, index) => new KeyValuePair<double, string>(Convert.ToDouble(index), item)).ToArray();
var matrixIndexes = MatrixValues.Select(x => x.Key);
var M = Matrix<double>.Build;
var C = M.Dense(datas.Count, datas.First().Array.Count(), matrixIndexes.ToArray());
var TR = C.Transpose();
string columns = "Device #".PadRight(10, ' ') + "\n" + "Pt.Name".PadRight(10, ' ');
StringBuilder sb = new StringBuilder(columns);
for (int i = 0; i < TR.Storage.Enumerate().Count(); i += 2)
{
sb = sb.AppendRight(MatrixValues[i].Value, MatrixValues[i + 1].Value);
}
Console.WriteLine(sb.ToString());
Console.ReadLine();
}
yea and those references
using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Output
PS: this may not be your desired solution as it is creating multiple string builders when you append new data
This should get you going:
Code
StringBuilder deviceSB = new StringBuilder();
StringBuilder patNameSB = new StringBuilder();
deviceSB.Append("Device #".PadRight(9));
patNameSB.Append("Pt.Name".PadRight(9));
foreach (var data in datas)
{
deviceSB.Append($"{data.Device}".PadLeft(2).PadRight(4));
patNameSB.Append($"{data.PatName} ");
}
deviceSB.AppendLine();
deviceSB.Append(patNameSB);
Or optional without loop
StringBuilder result = new StringBuilder();
StringBuilder s1 = new StringBuilder("Device # ".PadRight(9));
StringBuilder s2 = new StringBuilder("Pt.Name ".PadRight(9));
s1 = s1.AppendJoin(String.Empty, datas.Select(x => x.Device.PadLeft(2).PadRight(4)));
s2 = s2.AppendJoin(' ', datas.Select(x => x.PatName));
result = result.Append(s1).AppendLine().Append(s2);
Note that i took the idea of the second option from #AshkanMobayenKhiabani, but instead of using strings i stick to StringBuilder since it is much more performant than using strings!
Output
Both of previous options offer the same output:
I have an XML File that I want to allow the end user to set the format of a string.
ex:
<Viewdata>
<Format>{0} - {1}</Format>
<Parm>Name(property of obj being formatted)</Parm>
<Parm>Phone</Parm>
</Viewdata>
So at runtime I would somehow convert that to a String.Format("{0} - {1}", usr.Name, usr.Phone);
Is this even possible?
Of course. Format strings are just that, strings.
string fmt = "{0} - {1}"; // get this from your XML somehow
string name = "Chris";
string phone = "1234567";
string name_with_phone = String.Format(fmt, name, phone);
Just be careful with it, because your end user might be able to disrupt the program. Do not forget to FormatException.
I agree with the other posters who say you probably shouldn't be doing this but that doesn't mean we can't have fun with this interesting question. So first of all, this solution is half-baked/rough but it's a good start if someone wanted to build it out.
I wrote it in LinqPad which I love so Dump() can be replaced with console writelines.
void Main()
{
XElement root = XElement.Parse(
#"<Viewdata>
<Format>{0} | {1}</Format>
<Parm>Name</Parm>
<Parm>Phone</Parm>
</Viewdata>");
var formatter = root.Descendants("Format").FirstOrDefault().Value;
var parms = root.Descendants("Parm").Select(x => x.Value).ToArray();
Person person = new Person { Name = "Jack", Phone = "(123)456-7890" };
string formatted = MagicFormatter<Person>(person, formatter, parms);
formatted.Dump();
/// OUTPUT ///
/// Jack | (123)456-7890
}
public string MagicFormatter<T>(T theobj, string formatter, params string[] propertyNames)
{
for (var index = 0; index < propertyNames.Length; index++)
{
PropertyInfo property = typeof(T).GetProperty(propertyNames[index]);
propertyNames[index] = (string)property.GetValue(theobj);
}
return string.Format(formatter, propertyNames);
}
public class Person
{
public string Name { get; set; }
public string Phone { get; set; }
}
XElement root = XElement.Parse (
#"<Viewdata>
<Format>{0} - {1}</Format>
<Parm>damith</Parm>
<Parm>071444444</Parm>
</Viewdata>");
var format =root.Descendants("Format").FirstOrDefault().Value;
var result = string.Format(format, root.Descendants("Parm")
.Select(x=>x.Value).ToArray());
What about specify your format string with parameter names:
<Viewdata>
<Format>{Name} - {Phone}</Format>
</Viewdata>
Then with something like this:
http://www.codeproject.com/Articles/622309/Extended-string-Format
you can do the work.
Short answer is yes but it depends on the variety of your formatting options how difficult it is going to be.
If you have some formatting strings that accept 5 parameter and some other that accept only 3 that you need to take that into account.
I’d go with parsing XML for params and storing these into array of objects to pass to String.Format function.
You can use System.Linq.Dynamic and make entire format command editable:
class Person
{
public string Name;
public string Phone;
public Person(string n, string p)
{
Name = n;
Phone = p;
}
}
static void TestDynamicLinq()
{
foreach (var x in new Person[] { new Person("Joe", "123") }.AsQueryable().Select("string.Format(\"{0} - {1}\", it.Name, it.Phone)"))
Console.WriteLine(x);
}
Wonder if someone could point me in the right direction. What I'd like to achieve is to split a string based upon it having a '/' in it. For example if I had: www.site.com/course/123456/216 in code (c#) I'd like to be able to split the string in code so that 123456 could be assigned to variable param1 and 216 be assigned to param2 (course is the 'friendly' name of the page). If I was to add a third '/' on the string I'd like this to become param3, etc, etc.
Ideally I'd like to be able to put this code somewhere that I could include it on whichever usercontrols I'd need it to work.
Uri.Segments maybe what you are looking for:
new Uri("http://www.contoso.com/foo/bar/index.htm#search").Segments
Results in [ "/", "foo/", "bar/", "index.html" ]
Why not just use split?
var valueArray = "www.site.com/course/123456/216".Split('/');
The array will have the entire string broken up
index 0 would be "www.site.com" and so forth.
HttpContext.Current.Request.Url.AbsolutePath.Split('/')
Well, making the assumption that the values would not have / in them:
var splitVals = queryString.Split('/');
var vals = new Dictionary<string, string>();
for (int i = 2; i <= splitVals.Count; i++)
{
vals.Add(string.Format("param{0}", i), vals[i]);
}
That would get you started. Now, if you're looking to set them to real variables then you'd need to do some casting and leverage reflection, but your question isn't near clear enough to make any real assumptions there.
EDIT
To make this code reusable I would build an extension method:
namespace System
{
public static class StringExtensions
{
public static Dictionary<string, string> SplitQueryString(this string queryString)
{
var splitVals = queryString.Split('/');
var vals = new Dictionary<string, string>();
for (int i = 2; i <= splitVals.Count; i++)
{
vals.Add(string.Format("param{0}", i), vals[i]);
}
return vals;
}
}
}
because then you could do this:
var vals = queryString.SplitQueryString();
http://msdn.microsoft.com/en-us/library/b873y76a.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
string QueryString = "1234/567/890";
string[] QueryArray = QueryString.Split('/');
Now QueryArray[0] = 1234, QueryArray[1] = 567, QueryArray[2] = 890,
url: server/func2/SubFunc2
// Get path components. Trailing separators. Returns { "/", "func2/", "sunFunc2" }.
string[] pathsegments = myUri.Segments;
I have a list of strings.. each one looks similar to this:
"\n\t\"BLOCK\",\"HEADER-\"\r\n\t\t\"NAME\",\"147430\"\r\n\t\t\"REVISION\",\"0000\"\r\n\t\t\"DATE\",\"11/11/10\"\r\n\t\t\"TIME\",\"10:03:47\"\r\n\t\t\"PMABAR\",\"\"\r\n\t\t\"COMMENT\",\"\"\r\n\t\t\"PTPNAME\",\"0805C\"\r\n\t\t\"CMPNAME\",\"0805C\"\r\n\t\"BLOCK\",\"PRTIDDT-\"\r\n\t\t\"PMAPP\",1\r\n\t\t\"PMADC\",0\r\n\t\t\"ComponentQty\",4\r\n\t\"BLOCK\",\"PRTFORM-\"\r\n\t\t\....(more)...."
What I am trying to do is keep that entire string BUT... replace the DATE, TIME and ComponentQty.....
I want to place the date variable that i have set for the DATE, as well as the DateTime.Now.ToString(""HH:mm:ss") for the TIME ... and a dictionary[part] for the ComponentQty. These values would replace like so:
"DATE","11/11/10" with "DATE","12/06/11"
"TIME","10:03:47" with "TIME","10:30:10"
"ComponentQty",4 with "ComponentQty", 8
or something similar...
so the new string would look like this:
"\n\t\"BLOCK\",\"HEADER-\"\r\n\t\t\"NAME\",\"147430\"\r\n\t\t\"REVISION\",\"0000\"\r\n\t\t\"DATE\",\"12/06/11\"\r\n\t\t\"TIME\",\"10:30:10"\"\r\n\t\t\"PMABAR\",\"\"\r\n\t\t\"COMMENT\",\"\"\r\n\t\t\"PTPNAME\",\"0805C\"\r\n\t\t\"CMPNAME\",\"0805C\"\r\n\t\"BLOCK\",\"PRTIDDT-\"\r\n\t\t\"PMAPP\",1\r\n\t\t\"PMADC\",0\r\n\t\t\"ComponentQty\",8\r\n\t\"BLOCK\",\"PRTFORM-\"\r\n\t\t\....(more)...."
What is the quickest way to do such a thing? I was thinking Regex but I am not too sure on how to go about doing this. Can anyone help?
EDIT:
I used just a normal string replace to do it.. but the replaced data will not always have the statc date, time, compQty that I have below (11/11/10, 10:03:47, 4)... I need to find a way to make that section not hard coded -- with regex I am assuming..
var newDate = "DATE\",\"" + date + "\"";
var newTime = "TIME\",\"" + DateTime.Now.ToString("HH:mm:ss") + "\"";
var newCompQTY = "ComponentQty\"," + dictionary[part];
trimmedDataBasePart = trimmedDataBasePart.ToUpper().Replace("DATE\",\"11/11/10", newDate);
trimmedDataBasePart = trimmedDataBasePart.ToUpper().Replace("TIME\",\"10:03:47", newTime);
trimmedDataBasePart = trimmedDataBasePart.ToUpper().Replace("COMPONENTQTY\",4", newCompQTY);
I am trying to set a value to a Regex and am not sure how to do so... this is what I was trying... but it obviously does not work because the var is not a string. any suggestions?
var newDate = "DATE\",\"" + date + "\"";
var regexedDate = Regex.Match(trimmedDataBasePart, "DATE\",[0-9]+/[0-9]+/[0-9]+");
trimmedDataBasePart = trimmedDataBasePart.ToUpper().Replace(regexedDate, newDate);
Try this:
resultString = Regex.Replace(subjectString, #"(.*\bDATE\b\D*).*?(\\.*\bTIME\b\D*).*?(\\.*\bComponentQty\b\D*)\d+(.*)", "$1NEW_DATE$2NEW_TIME$3NEW_QTY", RegexOptions.Singleline);
Where NEW_DATE should be replaced by your date, NEW_TIME by your time, and NEW_QTY by your new qty.
You can create the replacement string from other variables as you please :)
Well well well, .NET and interpolated variables suck.. If you try to change use "$11" in replacement it thinks it has to use backreference #11 and it fails. Also Regexbuddy had a bug which produced the wrong regex. This is tested and works!
string subjectString = "\n\t\"BLOCK\",\"HEADER-\"\r\n\t\t\"NAME\",\"147430\"\r\n\t\t\"REVISION\",\"0000\"\r\n\t\t\"DATE\",\"11/11/10\"\r\n\t\t\"TIME\",\"10:03:47\"\r\n\t\t\"PMABAR\",\"\"\r\n\t\t\"COMMENT\",\"\"\r\n\t\t\"PTPNAME\",\"0805C\"\r\n\t\t\"CMPNAME\",\"0805C\"\r\n\t\"BLOCK\",\"PRTIDDT-\"\r\n\t\t\"PMAPP\",1\r\n\t\t\"PMADC\",0\r\n\t\t\"ComponentQty\",4\r\n\t\"BLOCK\",\"PRTFORM-\"\r\n\t\t....(more)....";
Regex regexObj = new Regex(#"^(.*\bDATE\b\D*).*?(\"".*?\bTIME\b\D*).*?(\"".*?\bComponentQty\b\D*)\d+(.*)$", RegexOptions.Singleline);
StringBuilder myResult = new StringBuilder();
Match matchResults = regexObj.Match(subjectString);
while (matchResults.Success)
{
for (int i = 1; i < matchResults.Groups.Count; i++)
{
Group groupObj = matchResults.Groups[i];
if (groupObj.Success)
{
myResult.Append(groupObj.Value);
switch (i)
{
case 1:
myResult.Append("NEW_DATE");
break;
case 2:
myResult.Append("NEW_TIME");
break;
case 3:
myResult.Append("NEW QTY");
break;
}
}
}
matchResults = matchResults.NextMatch();
}
Console.WriteLine("Final Result : \n\n\n{0}", myResult.ToString());
Output:
Final Result :
"BLOCK","HEADER-"
"NAME","147430"
"REVISION","0000"
"DATE","NEW_DATE"
"TIME","NEW_TIME"
"PMABAR",""
"COMMENT",""
"PTPNAME","0805C"
"CMPNAME","0805C"
"BLOCK","PRTIDDT-"
"PMAPP",1
"PMADC",0
"ComponentQty",NEW QTY
"BLOCK","PRTFORM-"
....(more)....
By the way you have a falsely escaped dot in your input string. Cheers and have fun! :)
If you can change the way your source string looks, I would use String.Format:
string s = String.Format("Date={0}, Name={1}, Quantity={2}", date, name, quantity);
The placeholders {0}, {1}, {2} are replaced with the specified arguments which follow.
To make it cleaner I would create a function to parse that string list, and then another function to create such a string list instead of using regexps. I think this will make your code easier to maintain.
Dictionary<string, string> Parse(List<string> data)
{
...
}
List<string> CreateStringList(Dictionary<string, string> values)
{
...
}
List<string> SetValues(List<string> data)
{
Dictionary<string, string> values = Parse(data);
values["DATE"] = "12/06/11";
values["TIME"] = "10:30:10";
values["ComponentQty"] = "4";
return CreateStringList(values);
}
Is there any method that I can use that returns a fixed length array after spliting a string with some delimiter and fill the rest with a default string.
Eg.
string fullName = "Jhon Doe";
string[] names = fullName.SpecialSplit(some parameters); //This should always return string array of length 3 with the second elememnt set to empty if there is no middle name.
Next time specify the language you're asking about. We're no guessers.
In Java:
fullName.split(" ");
And anyway, no method will "return string array of length 3 with the second elememnt set to empty if there is no middle name". For the method, there are just two elements. You have to write that method yourself wrapping the standard split() method.
You should read over Jon Skeet's Writing the perfect question. It will be beneficial to you in the future when posting questions of StackOverflow.
There is no method in C# to do what you are asking, but you can easily write an extension method to do what I think you are asking.
here is a quick example:
public static class AbreviatorExtention
{
public static string[] GetInitials(this String str, char splitChar)
{
string[] initialArray = new string[3];
var nameArray = str.Split(new char[] { splitChar },
StringSplitOptions.RemoveEmptyEntries);
if (nameArray.Length == 2)
{
var charArrayFirstName = nameArray[0].ToCharArray();
var charArrayLastName = nameArray[1].ToCharArray();
initialArray[0] = charArrayFirstName[0].ToString().ToUpper();
initialArray[1] = string.Empty;
initialArray[2] = charArrayLastName[0].ToString().ToUpper();
}
else
{
for (int i = 0; i < nameArray.Length; i++)
{
initialArray[i] = (nameArray[i].ToCharArray())[1]
.ToString().ToUpper();
}
}
return initialArray;
}
}
class Program
{
static void Main(string[] args)
{
string FullName = "john doe";
//Extension method in use
string[] names = FullName.GetInitials(' ');
foreach (var item in names)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
Output:
J
D
I would set it up to split the string separate from the fixed array. If you still want a fixed array, then you set up the array to a size of three an populate. This is not the best method, however, as it has no meaning. Better, set up a person or user class and then populate, via rules, from the split string.