Convert ProperCase to a sentence that is in the header (as opposed to a sentence case)

Hi, I would like to convert a word, which in the right case, into a sentence with a name. Example:

NumberOfLoyalHonestWomen will become

The number of faithful honest women

Basically, this method is combined with reflection to turn field / property names into people's shortcuts when they automatically generate inputs for the screen.

Here is what I got. Is there a better or cleaner way? Dot net fiddle

using System;
using System.Text.RegularExpressions;
using System.Linq;

public class Program
{
    public static void Main()
    {
        string testString = "ATCPConnection";
        Console.WriteLine(testString.ToSentence());
    }

}

public static class StringExtensions
{
    public static string ToSentence(this string Source)
    {
        return Regex.Replace(string.Concat(from Char c 
                                           in Source.ToCharArray()
                                           select Char.IsUpper(c) ? " " + c : c.ToString()).Trim(), 
                             "(?<AcronymLetter>[A-Z]) (?=[A-Z](?![a-z]))", 
                             "${AcronymLetter}");
    }

}

Side note. This was complicated by my desire to keep the acronyms intact, hence <<22>. For instance:

MGTOWSaysThereAreMoreUnicorns will become

MGTOW says there are more unicorns

+4
source share
4 answers

Here's a different approach:

  • , ( , ). PascalCased.
  • , . ACRONYMS.

:

public static string ToSentence(this string Source)
{
    Source = Regex.Replace(Source, "((?<!^)[A-Z][a-z])", " $1");
    Source = Regex.Replace(Source, "([a-z])([A-Z])", "$1 $2");
    return Source;
}

UPDATE: :

public static string ToSentence(this string Source)
{
    return Regex.Replace(Source, "(?<!^)[A-Z][a-z]|(?<=[a-z])[A-Z]", " $0");
}
+5

?

FYI: System.Runtime.CompilerServices.ExtensionAttribute #.
( VB.NET.)

this.

public static string ToSentence(this string value)
{
    char[] characters = value.ToCharArray();

    // Determine where groups start
    List<int> groupStartIndexes =
        characters
            .Select((character, index) =>
                new
                {
                    Character = character,
                    Index = index
                }
            )
            .Where(obj => Char.IsUpper(obj.Character))
            .Select(obj => obj.Index)
            .ToList();

    // if there is no upper case letter or
    // if value does not start with an upper case letter
    if (!groupStartIndexes.Contains(0))
    {
        groupStartIndexes.Insert(0, 0);
    }

    // To make our life easier
    groupStartIndexes.Add(value.Length);

    var groups = new List<string>();

    // Split value into groups
    for (int index = 0; index < groupStartIndexes.Count - 1; index++)
    {
        int currentGroupStartIndex = groupStartIndexes[index];
        int nextGroupStartIndex = groupStartIndexes[index + 1];

        string currentGroup =
            value
                .Substring(
                    currentGroupStartIndex,
                    nextGroupStartIndex - currentGroupStartIndex
                );

        groups.Add(currentGroup);
    }

    var sb = new StringBuilder(groups[0]);

    // Build the final string
    for (int currentGroupIndex = 1; currentGroupIndex < groups.Count; currentGroupIndex++)
    {
        string previousGroup = groups[currentGroupIndex - 1];
        string currentGroup = groups[currentGroupIndex];

        if (previousGroup.Length > 1 || currentGroup.Length > 1)
        {
            sb.Append(" ");
        }

        sb.Append(groups[currentGroupIndex]);
    }

    return sb.ToString();
}
+3

. .

public static string ToSentence(this string src) {
    var retVal = "";
    if (src.Length > 0) {
        List<string> wordCollection = new List<string>();
        int startIndex = 0;
        char[] letters = src.ToCharArray();
        //Skip the First Letter
        var length = letters.Length;
        for (int i = 1; i < length; i++) {
            if (char.IsUpper(letters[i])) {
                //Check for acronyms
                if (char.IsUpper(letters[i - 1])
                    && (
                           i == length - 1 ||
                           ((i + 1) < length && (char.IsUpper(letters[i + 1]) || char.IsNumber(letters[i + 1])))
                        )
                )
                    continue;

                //Grab Eeverything before Current Index
                var temp = new String(letters, startIndex, i - startIndex);
                wordCollection.Add(temp.Trim());
                startIndex = i;
            }
        }
        wordCollection.Add(new String(letters, startIndex, letters.Length - startIndex));
        retVal = String.Join(" ", wordCollection);
    }
    return retVal;
}

   public class TestCases {
        [DataDrivenTestMethod]
        [DataRow("NumberOfLoyalHonestWomen", "Number Of Loyal Honest Women")]
        [DataRow("MGTOWSaysThereAreMoreUnicorns", "MGTOW Says There Are More Unicorns")]
        [DataRow("MGTOW1SaysThereAreMoreUnicorns", "MGTOW1 Says There Are More Unicorns")]
        [DataRow("MGTOWSaysThereAreMOREUnicorns", "MGTOW Says There Are MORE Unicorns")]
        [DataRow("MGTOWSaysThereAREMoreUNICORNS", "MGTOW Says There ARE More UNICORNS")]            
        public void ConvertToTitleCase(string stringUnderTest, string expected) {
            var actual = stringUnderTest.ToSentence();
            Assert.AreEqual(expected, actual);
        }

    }
+2

This approach is similar to @ Gabor's, with some guarantees and optimizations. Although admittedly nowhere is as compact as the @MichaelLiunot regular expression solution, it should be much faster. I tested it against all the examples so far.

public static string ToSentence(this string value)
{
    if (value == null) return value;
    int length = value.Length;
    if (length <= 1) return value;

    var sb = new StringBuilder(value[0].ToString(), length);
    char currentChar;

    for (int ubound = length - 2, i = 1; i <= ubound; ++i)
    {
        currentChar = value[i];
        if (Char.IsUpper(currentChar) && (Char.IsLower(value[i - 1]) || Char.IsLower(value[i + 1])))
            sb.Append(' ');
        sb.Append(currentChar);
    }
    currentChar = value[length - 1];
    if (Char.IsUpper(currentChar) && Char.IsLower(value[length - 2]))
        sb.Append(' ');
    sb.Append(currentChar);
    return sb.ToString();
}
+1
source

All Articles