How to build a string from a collection of names

I have a set of first names that I need to concatenate into a comma separated string.

The generated string must adhere to the correct grammar.

If the collection contains one name, then the output should be only that name:

John 

If the collection contains two names, then the output should be separated by the word "and":

 John and Mary 

If the collection contains three or more names, then the output must be separated by a comma, and the last name must have the word "and" in front of it:

 John, Mary, and Jane 

Here is the code I came up with. This is not very elegant, and I would like to know if there is a better way to do this in C # (4.0 is fine).

 List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); string names = string.Empty; for (int i = 0; i < firstNames.Count; i++) { if (i == 1 && firstNames.Count == 2) { names += " and "; } else if (firstNames.Count > 2 && i > 0 && i != firstNames.Count - 1) { names += ", "; } else if (i != 0 && i == firstNames.Count - 1) { names += ", and "; } names += firstNames[i]; } 
+6
source share
11 answers

I do not think it will become more elegant than:

  if (names.Count == 0) return ""; if (names.Count == 1) return names[0]; if (names.Count == 2) return names[0] + " and " + names[1]; return String.Join(", ", names.Take(names.Count - 1)) + ", and " + names[names.Count - 1]; 

I did not compile this, but I think you understand this idea.

EDIT: shorter but less readable:

  if (names.Count <= 2) return String.Join(" and ", names); return String.Join(", ", names.Take(names.Count - 1)) + ", and " + names[names.Count - 1]; 
+6
source

I would do something like this:

 using System; using System.Collections.Generic; class Program { static void Main(string[] args) { List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); Console.WriteLine(NamesString(firstNames)); } static string NamesString(List<string> firstNames) { switch (firstNames.Count) { case 0: return string.Empty; case 1: return firstNames[0]; case 2: return string.Join(" and ", firstNames.ToArray()); default: return string.Format("{0} and {1}", string.Join(", ", firstNames.ToArray(), 0, firstNames.Count - 1), firstNames[firstNames.Count - 1]); } } } 

EDIT : really should be

  default: return string.Format("{0}, and {1}", 

if you want a comma before the last "and".

+3
source
  string a=string.Join(",", FirstNames.ToArray()); if (FirstNames.Count == 1) a.Replace(",", ""); else if (FirstNames.Count == 2) a.Replace(",", " and "); else { int i = a.LastIndexOf(","); a = a.Substring(1, i) + a.Substring(i).Replace(",", " and "); } 
+2
source
  static string JoinNames(List<string> firstNames) { int count = firstNames.Count; if(count == 1) { return firstNames[0]; } if(count > 1) { return string.Join(", ", firstNames.Take(count - 1).ToArray()) + " and " + firstNames[count - 1]; } return string.Empty; } 
+1
source
 List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); StringBuilder names = new StringBuilder(); for (int i = 0; i < firstNames.Count; i++) { if((i-1) == firstNames.Count && names.length > 0) names.AppendFormat(" and {0}", names[i]); else if(names.length > 0) names.AppendFormat(", {0}", names[i]); } return names.ToString(); 

I think this is the best way.

0
source
 List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); int cnt = 0; string names = string.Empty; while (cnt<=firstName.Count) { string separator = ""; if (firstName.Count - cnt > 1) separator = ", "; else if (firstName.Count - cnt = 1) separator = ", and "; else separator = ""; names += firstName[cnt] + separator; cnt += 1; } 
0
source

Here is an interesting solution:

  //code List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); StringBuilder sb = new StringBuilder(); firstNames.Take(firstNames.Count - 1).ToList().ForEach(fn => AddString(fn, sb)); sb.Append(", and " + firstNames.Last()); //Helper Function public void AddString (string fn, StringBuilder sb) { if (sb.Length != 0) { sb.Append(", "); } sb.Append(fn); } 
0
source

Try this for size:

  List<string> firstNames = new List<string>(); firstNames.Add("John"); firstNames.Add("Mary"); firstNames.Add("Jane"); // Only do this if there is more than one name if (firstNames.Count > 1) { string separator = ", "; // Join the names, using ", " as a separator string names = String.Join(seperator, firstNames.ToArray()); // Insert "and" before the last comma names = names.Insert(names.LastIndexOf(separator), ", and "); // Remove the last comma names = names.Remove(names.LastIndexOf(separator), separator.Length); } 
0
source
 var a = String.Join(", ", firstNames.Skip(1).ToArray()) + (firstNames.Count < 2 ? "" : ", and ") + firstNames.Take(1).FirstOrDefault(); 
0
source

I prefer the most readable code. You have four punctuation cases to consider when adding a name to the list, so just conjure them.

 static string Combine(List<string> names) { var sb = new StringBuilder(); for (int i = 0; i < names.Count; i++) { if (i == 0) //at start of a list {} else if (i < names.Count - 1) //in middle of list sb.Append(", "); else if( names.Count == 2 ) //at end of a list with 2 elements sb.Append(" and "); else //at end of a list with 3 or more elements sb.Append(", and "); sb.Append(names[i]); } return sb.ToString(); } 
0
source
 public string Combine(List<string> names) { if (names == null || names.Count == 0) { return string.Empty; } var sb = new StringBuilder(); sb.Append(names[0]); //Handle Special Case of 2 names if (names.Count == 2) { sb.Append(" and " + names[1]) return sb.ToString(); } for (int i = 1; i < names.Count; i++) { if (i == (names.Count -1)) { sb.Append(", and " + names[i]); } else { sb.Append(", " + names[i]); } } return sb.ToString(); } 
0
source

Source: https://habr.com/ru/post/891155/


All Articles