views:

2911

answers:

6

Given the string "ThisStringHasNoSpacesButItDoesHaveCapitals" what is the best way to add spaces before the capital letters. So the end string would be "This String Has No Spaces But It Does Have Capitals"

Here is my attempt with a RegEx

System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")
+1  A: 

What you have works perfectly. Just remember to reassign value to the return value of this function.

value = System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0");
Bill the Lizard
+17  A: 

Your solution has an issue in that it puts a space before the first letter T so you get

" This String..." instead of "This String..."

To get around this look for the lower case letter preceding it as well and then insert the space in the middle:

newValue = Regex.Replace(value, "([a-z])([A-Z])", "$1 $2");

Edit 1:

If you use "(\p{Ll})(\p{Lu})" it will pick up accented characters as well.

Edit 2:

If your strings can contain acronyms you may want to use this:

newValue = Regex.Replace(value, "((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))", " $0");

So "DriveIsSCSICompatible" becomes "Drive Is SCSI Compatible"

Martin Brown
Nice catch, and a nice, simple solution.
Bill the Lizard
Great answer, thanks!
Bob
A: 

Jason - Your method retuns: his tring as o paces ut t oes ave apitals

A: 

Here's mine:


private string SplitCamelCase(string s) 
        { 
            Regex upperCaseRegex = new Regex(@"[A-Z]{1}[a-z]*"); 
            MatchCollection matches = upperCaseRegex.Matches(s); 
            List words = new List(); 
            foreach (Match match in matches) 
            { 
                words.Add(match.Value); 
            } 
            return String.Join(" ", words.ToArray()); 
        }
Cory Foy
Is that supposed to be C#? If so what namespace is List in? Do you mean ArrayList or List<string>?
Martin Brown
List<string> would be fine. Sorry about that.
Cory Foy
+19  A: 

The regexes will work fine (I even voted up Martin Browns answer), but they are expensive

This function

string AddSpacesToSentence(string text)
{
        if (string.IsNullOrEmpty(text))
           return "";
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]))
                newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
}

Will do it 100,000 times in 2,968,750 ticks, the regex will take 25,000,000 ticks (and thats with the regex compiled).

It's better, for a given value of better (i.e. faster) however it's more code to maintain. "Better" is often compromise of competing requirements.

Hope this helps :)

Binary Worrier
Sres
+2  A: 

Hello, Binary Worrier, I have used your suggested code, and it is rather good, I have just one minor addition to it:

public static string AddSpacesToSentence(string text)
{
 if (string.IsNullOrEmpty(text))
  return "";
 StringBuilder newText = new StringBuilder(text.Length * 2);
 newText.Append(text[0]);
 for (int i = 1; i < text.Length; i++)
 {
  if (char.IsUpper(text[i]) && !char.IsUpper(text[i - 1]))
   newText.Append(' ');
  newText.Append(text[i]);
 }
 return newText.ToString();
}

I have added a condition !char.IsUpper(text[i - 1]) This has fixed a bug that would cause something like 'AverageNOX' to be turned into 'Average N O X', which is obviously wrong, as it should read 'Average NOX'.

Sadly this still has the bug that if you have the text 'FromAStart', you would get 'From AStart' out.

Any thoughts on fixing this?

Richard Priddy
Martin Brown