2

How do I convert "ThisIsMyTestString" into "This Is My Test String" using C#?

Is there a fast way to do it?

I've been thinking of a pseudo code but it's complicated and ugly:

String s = "ThisIsMyTestString";

List<String> strList = new List<String>();
for(int i=0; i < str->Length ; i++)
{
   String tmp = "";
   if (Char.IsUpper(str[i]))
   {
     tmp += str[i];
     i++;
   }

   while (Char::IsLower(str[i]))
   {
     tmp += str[i];
     i++;
   }

   strList .Add(tmp);
}

String tmp2 = "";
for (uint i=0 ; i<strList.Count(); i++)
{
  tmp2 += strList[i] + " ";
}
JoshDM
  • 4,939
  • 7
  • 43
  • 72
Dardar
  • 624
  • 3
  • 13
  • 30
  • Very similar question here: http://stackoverflow.com/questions/291804/split-a-pascal-case-string-into-logical-set-of-words – Curtis Rutland Jul 15 '13 at 15:18
  • personally I'd split anytime you find a char that is `< 97` – Sayse Jul 15 '13 at 15:18
  • 3
    What is the output of the code you wrote? Saying "its so ugly I am not even trying to fix it" indicates your not willing to go to the effort to debug your own code. – Security Hound Jul 15 '13 at 15:19
  • I see only one string in "This Is My Test String". Are you sure you want to separate one string in multiple strings? – C.Champagne Jul 15 '13 at 15:20
  • To author: Why you think that this way is ugly way? Of course, there is better solution with regexes, but ... That's nice too. Of course you must use StringBuilder for tmp variable, must write this code more nice-styled – Viktor Lova Jul 15 '13 at 15:20

4 Answers4

5

You can use Regex as outlined here:

Regular expression, split string by capital letter but ignore TLA

Your regex: "((?<=[a-z])[A-Z]|A-Z)"

Find and replace with " $1"

string splitString = Replace("ThisIsMyTestString", "((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))", " $1")

Here (?<=...) is a "positive lookbehind, a regex that should precede the match. In this case the lookbehind is "characters 'a' through 'z'" (?=...) is a similar construct with lookahead, where the match has to be followed by regex-described string. In this case the lookahead is "characters 'a' through 'z'" In both cases the final match contains one character "A" through "Z" followed by 'a'-'z' OR one character 'a' through 'z' followed by a capital letter. Replacing these matches puts a space between the capital and lowercase letters

Community
  • 1
  • 1
Sten Petrov
  • 10,943
  • 1
  • 41
  • 61
3

Not best code, but it works

String.Join("", s.Select(c => Char.IsUpper(c) ? " " + c : c.ToString())).Trim()
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
1

lazyberezovsky beat me with a much simpler solution... but this creates less garbage so I won't delete it.

static void Main(string[] args)
{
    Console.WriteLine(SplitByCase("ThisIsMyString"));
    Console.ReadLine();
}

static string SplitByCase(string str, bool upper = true)
{
    return String.Join(" ", SplitIntoWords(str, c => Char.IsUpper(c)));
}

static IEnumerable<String> SplitIntoWords(string str, Func<char, bool> splitter)
{
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < str.Length; i++)
    {
        sb.Append(str[i]);
        if (i + 1 == str.Length || splitter(str[i + 1]))
        {
            yield return sb.ToString();
            sb.Clear();
        }
    }
}
NPSF3000
  • 2,421
  • 15
  • 20
0

This will do it for that string:

            String s = "ThisIsMyTestString";
            StringBuilder result = new StringBuilder();
            result.Append(s[0]);
            for (int i = 1; i < s.Length; i++)
            {
                if (char.IsUpper(s[i]) )
                    result.Append(' ');
                result.Append(s[i]);
            }
            s = result.ToString();
terrybozzio
  • 4,424
  • 1
  • 19
  • 25