Join List<string> Together with Commas Plus "and" for Last Element

You could do this

string finalString = String.Join(", ", myList.ToArray(), 0, myList.Count - 1) + ", and " + myList.LastOrDefault();

Here is a solution which works with empty lists and list with a single item in them:

C#

return list.Count() > 1 ? string.Join(", ", list.Take(list.Count() - 1)) + " and " + list.Last() : list.FirstOrDefault();

VB

Return If(list.Count() > 1, String.Join(", ", list.Take(list.Count() - 1)) + " and " + list.Last(), list.FirstOrDefault())

I use the following extension method (with some code guarding too):

public static string OxbridgeAnd(this IEnumerable<String> collection)
{
    var output = String.Empty;

    var list = collection.ToList();

    if (list.Count > 1)
    {
        var delimited = String.Join(", ", list.Take(list.Count - 1));

        output = String.Concat(delimited, ", and ", list.LastOrDefault());
    }

    return output;
}

Here is a unit test for it:

 [TestClass]
    public class GrammarTest
    {
        [TestMethod]
        public void TestThatResultContainsAnAnd()
        {
            var test = new List<String> { "Manchester", "Chester", "Bolton" };

            var oxbridgeAnd = test.OxbridgeAnd();

            Assert.IsTrue( oxbridgeAnd.Contains(", and"));
        }
    }

EDIT

This code now handles null and a single element:

  public static string OxbridgeAnd(this IEnumerable<string> collection)
    {
        var output = string.Empty;

        if (collection == null) return null;

        var list = collection.ToList();

        if (!list.Any()) return output;

        if (list.Count == 1) return list.First();

        var delimited = string.Join(", ", list.Take(list.Count - 1));

        output = string.Concat(delimited, ", and ", list.LastOrDefault());

        return output;
    }

Tags:

C#

List