HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Extension method splitting string on each capital letter

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
eachmethodsplittingextensionletterstringcapital

Problem

I'm creating my own game and for some statistics I need to get the names of specific objects. The problem was that I had them declared like "SmallFireBall" but I wanted them to appear like"Small Fire Ball" because that's something the user is able to see, so I decided to create my own extension method to help me out:

public static string SplitOnCapitalLetters(this string inputString)
{
    List cleanString = inputString.ToList();
    for (int i = 1; i < cleanString.Count; i++)
    {
        if (char.IsUpper(cleanString[i]))
        {
            char[] temp = new char[cleanString.Count - i];
            for (int j = 0; j < temp.Length; j++)
            {
                temp[j] = cleanString[j + i];
            }
            cleanString[i] = ' ';
            cleanString.Add(' ');
            int index = 0;
            for (int j = i + 1; j < cleanString.Count; j++)
            {
                cleanString[j] = temp[index];
                index++;
            }
            i++;
        }
    }
    return new string(cleanString.ToArray());
}


However, I'm not quite confident about it. It seems quite big and maybe a little bit ugly, so please address any performance or code style issues.

Solution

With regex it's virtually a one-liner:

var words = 
    Regex.Matches("SmallFireBall", @"([A-Z][a-z]+)")
    .Cast()
    .Select(m => m.Value);

var withSpaces = string.Join(" ", words);


  • Regex.Matches - searches an input string for all occurrences of a regular expression and returns all the matches. MSDN



  • [A-Z][a-z]+ - matches strings that begin with a capital letter and are followed by one or more lowercase letters



Output:


Small Fire Ball

Let's review your code anyway and optimize it a little bit. Even without regex it still can be very short.

  • Use a StringBuilder for building string dynamically



-
You can use a foreach loop for strings too

public static string SplitOnCapitalLetters2(this string inputString)
{
    var result = new StringBuilder();

    foreach (var ch in inputString)
    {
        if (char.IsUpper(ch) && result.Length > 0)
        {
            result.Append(' ');
        }
        result.Append(ch);
    }
    return result.ToString();
}


The 3rd alternative would be only LINQ:

public static string SplitOnCapitalLetters3(this string inputString)
{
    // starts with an empty string and accumulates the new string into 'result'
    // 'next' is the next character
    return inputString.Aggregate(string.Empty, (result, next) =>
    {
        if (char.IsUpper(next) && result.Length > 0)
        {
            result += ' ';
        }
        return result + next;
    });
}

Code Snippets

var words = 
    Regex.Matches("SmallFireBall", @"([A-Z][a-z]+)")
    .Cast<Match>()
    .Select(m => m.Value);

var withSpaces = string.Join(" ", words);
public static string SplitOnCapitalLetters2(this string inputString)
{
    var result = new StringBuilder();

    foreach (var ch in inputString)
    {
        if (char.IsUpper(ch) && result.Length > 0)
        {
            result.Append(' ');
        }
        result.Append(ch);
    }
    return result.ToString();
}
public static string SplitOnCapitalLetters3(this string inputString)
{
    // starts with an empty string and accumulates the new string into 'result'
    // 'next' is the next character
    return inputString.Aggregate(string.Empty, (result, next) =>
    {
        if (char.IsUpper(next) && result.Length > 0)
        {
            result += ' ';
        }
        return result + next;
    });
}

Context

StackExchange Code Review Q#133707, answer score: 19

Revisions (0)

No revisions yet.