Jason Towne
Jason Towne

Reputation: 8050

Create user-readable, display-friendly formatted string from List<string>

I know several questions have been asked and answered about how to create a comma delimited string from a list. I'm looking for help on something slightly different.

What I would like to do is create a display-friendly human-readable string from a List<string> that reads like "A, B and C are invalid values". The grammar and format of the string should change based on the number of items in the list. The list could contain any number of items.

For example:

List<string> myString = new List<string>() { "Scooby", "Dooby", "Doo" };
// Should return "Scooby, Dooby and Doo are invalid values."

List<string> myString = new List<string>() { "Scooby", "Dooby" };
// Should return "Scooby and Dooby are invalid values."

List<string> myString = new List<string>() { "Scooby" };
// Should return "Scooby is an invalid value."

Here's what I've done so far:

string userMessage = "";
foreach(string invalidValue in invalidValues)
{
  userMessage = " " + userMessage + invalidValue + ",";
}

// Remove the trailing comma
userMessage = userMessage.Substring(0, userMessage.LastIndexOf(','));

if (invalidValues.Count > 1)
{
  int lastCommaLocation = userMessage.LastIndexOf(',');
  userMessage = userMessage.Substring(0, lastCommaLocation) + " and " + userMessage.Substring(lastCommaLocation + 1) + " are invalid values.";
}
else 
{
  userMessage = userMessage + " is an invalid value.";
}

Is there a better or more efficient way to do this?

Upvotes: 2

Views: 673

Answers (2)

Le Mot Juiced
Le Mot Juiced

Reputation: 3851

Heavily indebted to @Lee in his other answer, here's a much-expanded version of his method. It allows you to specify a beginning text and/or an ending text, and it uses the Oxford comma, the omission of which, as we all know, once had catastrophic results for the plaintiff in a lawsuit... but if you hate the darn thing you can just remove it from the method as written.

        public static string GrammaticallyCorrectStringFrom(List<string> items, string prefaceTextWithNoSpaceAtEnd, string endingTextWithoutPeriod)
    {
        var returnString = string.Empty;
        if (items.Count != 0)
        {
            returnString = prefaceTextWithNoSpaceAtEnd + " ";
        }
        if (items.Count == 1)
        {
            returnString += string.Format("{0}", items[0]);
        }
        else if (items.Count == 2)
        {
            returnString += items[0] + " and " + items[1];
        }
        else if (items.Count > 2)
        {
            //remove the comma in the string.Format part if you're an anti-Oxford type
            returnString += string.Format("{0}, and {1}", string.Join(", ", items.Take(items.Count - 1)), items.Last());
        }
        if (String.IsNullOrEmpty(returnString) == false)
        {
            returnString += endingTextWithoutPeriod + ".";
        }           
        return returnString;
    }

There's probably a better, less-verbose way to do the same thing, but this is working for me, and it's hard to argue with results. Actually I guess it isn't, here, but still... Anyway, anyone with a fire to improve this is welcome to.

Upvotes: 0

Lee
Lee

Reputation: 144136

public static string FormatList(List<string> invalidItems)
{
    if(invalidItems.Count == 0) return string.Empty;
    else if(invalidItems.Count == 1) return string.Format("{0} is an invalid value", invalidItems[0]);
    else return string.Format("{0} and {1} are invalid values", string.Join(", ", invalidItems.Take(invalidItems.Count - 1)), invalidItems.Last());
}

Upvotes: 8

Related Questions