Add string to List<string> - c#

I'm working on a method which takes a string and separates it into numerous items and then stores it inside of an array. I then perform a check to see if the array contains more than two items and if it does I assign specific items within an array to corresponding strings i.e. assign first item to forename, last item to surname and all other items to middle-name.
My issue relates to retrieving each of the items within the array which are not the first or last items and then assigning them in the correct order to a string. Below you can see that I have attempted to grab each item within the name array and assign the result to a list which can then be converted into a single string, but with no luck. What I am looking for is a solution to this problem.
public string SplitName(string text)
{
string forename;
string middlename;
string surname;
var name = text.Split(' ');
if (name != null)
{
if (name.Length > 2)
{
forename = name[0];
surname = name[name.Length - 1];
List<string> temp = new List<string>();
for (int i = 1; i < name.Length - 1; i++)
{
// Assign each item to middlename
}
text = string.Format("{0} {1} {2}", forename, middlename, surname);
}
}
else
{
text = "INVALID";
}
return text;
}

Use String.Join (http://msdn.microsoft.com/en-us/library/tk0xe5h0.aspx)
public string SplitName(string text)
{
string forename;
string middlename;
string surname;
var name = text.Split(' ');
if (name != null)
{
if (name.Length > 2)
{
forename = name[0];
surname = name[name.Length - 1];
middlename = string.Join(" ", name, 1, name.Length - 2);
text = string.Format("{0} {1} {2}", forename, middlename, surname);
}
}
else
{
text = "INVALID";
}
return text;
}
Change the first parameter of join (" ") if you want them to be joined using a different string. Currently a name "Bob Jack Willis Mills" will create a middlename "Jack Willis". If you want "Jack, Willis" use ", " as the separator.

If all you want to do is keep the first and last tokens separately and treat everything else as the middle name it would be much simpler to use a regular expression:
var regex = new Regex(#"^(\S+)\s+(?:(.*?)(?:\s+)?)(\S+)$");
var match = regex.Match("foo bar baz");
if (match.Success) {
var firstName = match.Groups[1].Value;
var middleName = match.Groups[2].Value;
var lastName = match.Groups[3].Value;
}
else {
// there were no spaces, i.e. just one token
}
The regular expression matches two runs of non-space characters at the ends with \S+. It optionally matches anything else that happens to be between them with the pattern (?:(.*?)(?:\s+)?), where the important part is (.*?) (match anything, non-greedy in order to not munch up any spaces before the last name) and the rest is mostly red tape (non-capturing groups, optional spaces before the lastname).

Try with this:
public string SplitName(string text)
{
string forename;
string middlename;
string surname;
var name = text.Split(' ');
if (name != null)
{
if (name.Length > 2)
{
forename = name[0];
surname = name[name.Length - 1];
middlename = string.Join(" ", name.Skip(1).Take(name.Length - 2));
text = string.Format("{0} {1} {2}", forename, middlename, surname);
}
}
else
{
text = "INVALID";
}
return text;
}
But this return exactly the same string.

First, you need to initialize the string variable, then you can just append all "middle" items to it.
public string SplitName(string text)
{
string forename = string.Empty;
string middlename = string.Empty;
string surname = string.Empty;
var name = text.Split(' ');
if (name != null)
{
if (name.Length > 2)
{
forename = name[0];
surname = name[name.Length - 1];
List<string> temp = new List<string>();
for (int i = 1; i < name.Length - 1; i++)
{
middlename += name[i];
}
text = string.Format("{0} {1} {2}", forename, middlename, surname);
}
}
else
{
text = "INVALID";
}
return text;
}

This will add all middlenames to middlename separated with space and trim last space
for (int i = 1; i < name.Length - 1; i++)
{
middlename+=name[i]+" ";
}
middlename = middlename.Trim(); // just for sure
If you need something else please specify your question
if your name is
aa bb cc dd ee
midlename will be
bb cc dd

Related

C# Get Initials of DisplayName

I'm trying to extract initials from a display name to be used to display their initials.
I'm finding it difficult because the string is one value containing one word or more. How can I achieve this?
Example:
'John Smith' => JS
'Smith, John' => SJ
'John' => J
'Smith' => S
public static SearchDto ToSearchDto(this PersonBasicDto person)
{
return new SearchDto
{
Id = new Guid(person.Id),
Label = person.DisplayName,
Initials = //TODO: GetInitials Code
};
}
I used the following solution: I created a helper method which allowed me to test for multiple cases.
public static string GetInitials(this string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return string.Empty;
}
string[] nameSplit = name.Trim().Split(new string[] { ",", " " }, StringSplitOptions.RemoveEmptyEntries);
var initials = nameSplit[0].Substring(0, 1).ToUpper();
if (nameSplit.Length > 1)
{
initials += nameSplit[nameSplit.Length - 1].Substring(0, 1).ToUpper();
}
return initials;
}
Or just another variation as an extension method, with a small amount of sanity checking
Given
public static class StringExtensions
{
public static string GetInitials(this string value)
=> string.Concat(value
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Where(x => x.Length >= 1 && char.IsLetter(x[0]))
.Select(x => char.ToUpper(x[0])));
}
Usage
var list = new List<string>()
{
"James blerg Smith",
"Michael Smith",
"Robert Smith 3rd",
"Maria splutnic Garcia",
"David Smith",
"Maria Rodriguez",
"Mary Smith",
"Maria Hernandez"
};
foreach (var name in list)
Console.WriteLine(name.GetInitials());
Output
JBS
MS
RS
MSG
DS
MR
MS
MH
Full Demo Here
Simple and easy to understand code and handles names which contain first, middle and last name such as "John Smith William".
Test at: https://dotnetfiddle.net/kmaXXE
Console.WriteLine(GetInitials("John Smith")); // JS
Console.WriteLine(GetInitials("Smith, John")); // SJ
Console.WriteLine(GetInitials("John")); // J
Console.WriteLine(GetInitials("Smith")); // S
Console.WriteLine(GetInitials("John Smith William")); // JSW
Console.WriteLine(GetInitials("John H Doe")); // JHD
static string GetInitials(string name)
{
// StringSplitOptions.RemoveEmptyEntries excludes empty spaces returned by the Split method
string[] nameSplit = name.Split(new string[] { "," , " "}, StringSplitOptions.RemoveEmptyEntries);
string initials = "";
foreach (string item in nameSplit)
{
initials += item.Substring(0, 1).ToUpper();
}
return initials;
}
How about the following:
void Main()
{
Console.WriteLine(GetInitials("John Smith"));
Console.WriteLine(GetInitials("Smith, John"));
Console.WriteLine(GetInitials("John"));
Console.WriteLine(GetInitials("Smith"));
}
private string GetInitials(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return string.Empty;
}
var splitted = name?.Split(' ');
var initials = $"{splitted[0][0]}{(splitted.Length > 1 ? splitted[splitted.Length - 1][0] : (char?)null)}";
return initials;
}
Output:
JS - SJ - J - S
the code below is from here. what the code does is take the first letter of every word from the string and outputs it as capital letters.
static void printInitials(String name)
{
if (name.Length == 0)
return;
// Since touuper() returns int,
// we do typecasting
Console.Write(Char.ToUpper(name[0]));
// Traverse rest of the string and
// print the characters after spaces.
for (int i = 1; i < name.Length - 1; i++)
if (name[i] == ' '&((i + 1)!=name.Length))
Console.Write(" " + Char.ToUpper(name[i + 1]));
}

C# slicing/assigning variables

String input;
Console.WriteLine(":>");
input = (Console.ReadLine());
string[] column = input.Split(' ');
int number_of_elements = column.Count(s => s != null);//counts the number of elements inputted
if (number_of_elements > 7 && column[0].ToLower() == "add") {
**String firstName = column[1, number_of_elements-6];**
String lastName = column[number_of_elements-5];
String id_Clause = column[number_of_elements-4];
String id_Number = column[number_of_elements-3];
String as_Clause = column[number_of_elements-2];
String as_Level = column[number_of_elements-1];
}
I am trying to make a C# program that takes values like this
ADD Mary Jane Watson ID 123456 AS Advanced
I am trying to make
String firstName = Mary Jane;
String lastName = Watson;
String id_Clause = ID
String id_Number = 123456
String as_Clause = AS
String as_Level = Advanced
THe last name Watson but everything between ADD and Watson as First Name.
So if the input was
ADD Mary Jane Jennifer Watson ID 123456 AS Advanced
then the result would be
String firstName = Mary Jane Jennifer;
String lastName = Watson;
String id_Clause = ID
String id_Number = 123456
String as_Clause = AS
String as_Level = Advanced
Use String.Join
Something like:
firstName = String.Join(" ", column, 1, number_of_elements - 6);
You could use .split(' ') but since you don't know the actual length of the name and you don't have any other delimiters this is difficult.
some things you could do:
String[] splitValues = "ADD Mary Jane Watson ID 123456 AS Advanced".Split(' ');
String lastName = splitValues[splitValues.Length-5]
String id_Clause = splitValues[splitValues.Length-4]
String id_Number = splitValues[splitValues.Length-3]
String as_Clause = splitValues[splitValues.Length-2]
String as_Level = splitValues[splitValues.Length-1]
and for the first name take the remaining values, skipping the first. which is the ADD.
This is just an example, but i hope you get the point. Also, it doesn't cover the cases where the last name is made from multiple pieces.
Get the index of ID-token.
var s = input.Split(' ');
var indexID = Array.FindIndex(s, a => a == "ID");
To get the first names skip ADD-token and take 2 less than the index (to avoid the surname and the ID-token).
string firstName = String.Join(" ", s.Skip(1).Take(indexID - 2));
Similarly use the index to get the last name and the idNumber
string lastName = s[indexID - 1];
string idNumber = s[indexID + 1];
The level is the last entry in the array.
string asLevel = s[s.Length - 1];
Below is a full sample program.
static void Main(string[] args)
{
string[] inputs = new string[] { "ADD Mary Jane Watson ID 123456 AS Advanced", "ADD Mary Jane Jennifer Watson ID 123456 AS Advanced" };
foreach (string input in inputs)
{
Console.WriteLine(Extract(input).ToString());
}
}
private static Person Extract(string input)
{
var s = input.Split(' ');
var indexID = Array.FindIndex(s, a => a == "ID");
string firstName = String.Join(" ", s.Skip(1).Take(indexID - 2));
string lastName = s[indexID - 1];
string idNumber = s[indexID + 1];
string asLevel = s[s.Length - 1];
return new Person()
{
FirstName = firstName,
LastName = lastName,
IDNumber = idNumber,
ASLevel = asLevel
};
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string IDNumber { get; set; }
public string ASLevel { get; set; }
public override string ToString()
{
return FirstName + " " + LastName + " " + IDNumber + " " + ASLevel;
}
}

C# Index of for space and next informations

Please, can you help me please. I have complete select adress from DB but this adress contains adress and house number but i need separately adress and house number.
I created two list for this distribution.
while (reader_org.Read())
{
string s = reader_org.GetString(0);
string ulice, cp, oc;
char mezera = ' ';
if (s.Contains(mezera))
{
Match m = Regex.Match(s, #"(\d+)");
string numStr = m.Groups[0].Value;
if (numStr.Length > 0)
{
s = s.Replace(numStr, "").Trim();
int number = Convert.ToInt32(numStr);
}
Match l = Regex.Match(s, #"(\d+)");
string numStr2 = l.Groups[0].Value;
if (numStr2.Length > 0)
{
s = s.Replace(numStr2, "").Trim();
int number = Convert.ToInt32(numStr2);
}
if (s.Contains('/'))
s = s.Replace('/', ' ').Trim();
MessageBox.Show("Adresa: " + s);
MessageBox.Show("CP:" + numStr);
MessageBox.Show("OC:" + numStr2);
}
else
{
Definitions.Ulice.Add(s);
}
}
You might find the street name consists of multiple words, or the number appears before the street name. Also potentially some houses might not have a number. Here's a way of dealing with all that.
//extract the first number found in the address string, wherever that number is.
Match m = Regex.Match(address, #"((\d+)/?(\d+))");
string numStr = m.Groups[0].Value;
string streetName = address.Replace(numStr, "").Trim();
//if a number was found then convert it to numeric
//also remove it from the address string, so now the address string only
//contains the street name
if (numStr.Length > 0)
{
string streetName = address.Replace(numStr, "").Trim();
if (numStr.Contains('/'))
{
int num1 = Convert.ToInt32(m.Groups[2].Value);
int num2 = Convert.ToInt32(m.Groups[3].Value);
}
else
{
int number = Convert.ToInt32(numStr);
}
}
Use .Split on your string that results. Then you can index into the result and get the parts of your string.
var parts = s.Split(' ');
// you can get parts[0] etc to access each part;
using (SqlDataReader reader_org = select_org.ExecuteReader())
{
while (reader_org.Read())
{
string s = reader_org.GetString(0); // this return me for example KarlĂ­nkova 514 but i need separately adress (karlĂ­nkova) and house number (514) with help index of or better functions. But now i dont know how can i make it.
var values = s.Split(' ');
var address = values.Count > 0 ? values[0]: null;
var number = values.Count > 1 ? int.Parse(values[1]) : 0;
//Do what ever you want with address and number here...
}
Here is a way to split it the address into House Number and Address without regex and only using the functions of the String class.
var fullAddress = "1111 Awesome Point Way NE, WA 98122";
var index = fullAddress.IndexOf(" "); //Gets the first index of space
var houseNumber = fullAddress.Remove(index);
var address = fullAddress.Remove(0, (index + 1));
Console.WriteLine(houseNumber);
Console.WriteLine(address);
Output: 1111
Output: Awesome Point Way NE, WA 98122

How to separate a first name and last name in c#?

I am looking for how to get rid off below exception "Index was outside the bounds of the array." for the below case 2
Aim: To separate the first name and last name (last name may be null some times)
Case 1:
Name: John Melwick
I can be able to resolve the first case with my code
Case 2:
Name: Kennedy
In case two I am getting an error Index was out of range at LastName in my code
Case 3:
Name: Rudolph Nick Bother
In case 3, I can be able to get:
FirstName: Rudolph and LastName: Nick (whereas I need Nick Bother together to be lastname)
Very much thankful, if anybody help me.
Here is the code:
Match Names = Regex.Match(item[2], #"(((?<=Name:(\s)))(.{0,60})|((?<=Name:))(.{0,60}))", RegexOptions.IgnoreCase);
if (Names.Success)
{
FirstName = Names.ToString().Trim().Split(' ')[0];
LastName = Names.ToString().Trim().Split(' ')[1];
}
Split the string with a limit on the number of substrings to return. This will keep anything after the first space together as the last name:
string[] names = Names.ToString().Trim().Split(new char[]{' '}, 2);
Then check the length of the array to handle the case of only the lastname:
if (names.Length == 1) {
FirstName = "";
LastName = names[0];
} else {
FirstName = names[0];
LastName = names[1];
}
Use
String.indexof(" ")
And
string.lastindexof(" ")
if they match there is one space. If they dont there is 2. I believe it returns 0 if there are no matches. Hope this helps
edit
if you use the indexes you can do a substring using them and get the last name as you are wanting
Something like this works:
string name = "Mary Kay Jones" ;
Regex rxName = new Regex( #"^\s*(?<givenName>[^\s]*)(\s+(?<surname>.*))?\s*$") ;
Match m = rxName.Match( name ) ;
string givenName = m.Success ? m.Groups[ "givenName" ].Value : "" ;
string surname = m.Success ? m.Groups[ "surname" ].Value : "" ;
But it is an extremely erroneous assumption that a given name consists only of a single word. I can think of many examples to the contrary, such as (but by no means limited to):
Billy Ray (as in the earlier example of "Billy Ray Cyrus")
Mary Kay
Mary Beth
And there's no real way to know without asking the person in question. Does "Mary Beth Jones" consist a given, middle and surname or does consist of a given name, Mary Beth and a surnname "Jones".
If you are considering English-speaking cultures, the usual convention is that one may have as many given names (forenames) followed by a family name (surname). Prince Charles, heir to the British Crown, for instance carries the rather heavy-duty Charles Phillip Arthur George Mountbatten-Windsor. Strictly speaking, he has no surname. Mountbatten-Windsor is used when one is required and his full name is just "Charles Phillip Arthur George".
string fullName = "John Doe";
var names = fullName.Split(' ');
string firstName = names[0];
string lastName = names[1];
The reason you're getting an error is because you're not checking for the length of names.
names.Length == 0 //will not happen, even for empty string
names.Length == 1 //only first name provided (or blank)
names.Length == 2 //first and last names provided
names.Length > 2 //first item is the first name. last item is the last name. Everything else are middle names
See this answer for more information.
Modify the code to be something like:
Match Names = Regex.Match(item[2], #"(((?<=Name:(\s)))(.{0,60})|((?<=Name:))(.{0,60}))", RegexOptions.IgnoreCase);
if (Names.Success)
{
String[] nameParts = Names.ToString().Trim().Split(' ');
int count = 0;
foreach (String part in nameParts) {
if(count == 0) {
FirstName = part;
count++;
} else {
LastName += part + " ";
}
}
}
Here is the most generalized solution for this issue.
public class NameWrapper
{
public string FirstName { get; set; }
public string LastName { get; set; }
public NameWrapper()
{
this.FirstName = "";
this.LastName = "";
}
}
public static NameWrapper SplitName(string inputStr, char splitChar)
{
NameWrapper w = new NameWrapper();
string[] strArray = inputStr.Trim().Split(splitChar);
if (string.IsNullOrEmpty(inputStr)){
return w;
}
for (int i = 0; i < strArray.Length; i++)
{
if (i == 0)
{
w.FirstName = strArray[i];
}
else
{
w.LastName += strArray[i] + " ";
}
}
w.LastName = w.LastName.Trim();
return w;
}

get values from array and add into one string

Object Book has Author which has property Name of type string.
I want to iterate trough all Authors and add it's Name string to the one string (not array) separated by comma, so this string should be at the as
string authorNames = "Author One, Author two, Author three";
string authorNames = string.Empty;
foreach(string item in book.Authors)
{
string fetch = item.Name;
??
}
You can use the string.Join function with LINQ
string authorNames = string.Join(", ", book.Authors.Select(a => a.Name));
You can use
string authors = String.Join(", ", book.Authors.Select(a => a.Name));
LINQ is the way to go in C#, but for explanatory purposes here is how you could code it explicitly:
string authorNames = string.Empty;
for(int i = 0; i < book.Authors.Count(); i++)
{
if(i > 0)
authorNames += ", ";
authorNames += book.Authors[i].Name;
}
You could also loop through them all, and append them to authorNames and add a comma in the end, and when it's done simply trim of the last comma.
string authorNames = string.Empty;
foreach(string author in book.Authors)
{
string authorNames += author.Name + ", ";
}
authorNames.TrimEnd(',');
Using LinQ, there are plenty of ways to merge multiple string into one string.
book.Authors.Select(x => x.Name).Aggregate((x, y) => x + ", " + y);
To anwsers James' comment
[TestMethod]
public void JoinStringsViaAggregate()
{
var mystrings = new[] {"Alpha", "Beta", "Gamma"};
var result = mystrings.Aggregate((x, y) => x + ", " + y);
Assert.AreEqual("Alpha, Beta, Gamma", result);
}

Categories