# Replace fifth space with new line

Posted on

Problem

I want to replace the fifth space in a sentence with a new line. Sample input:

“Hi this is empty string. This should be in new line!”

Expected output:

“Hi this is empty string.

This should be in new line!”

I’m getting the expected output with this code, but I need to know, is this the optimized solution or there are any better solution than this?

``````    string s = "Hi this is empty string. This should be in new line!", t = "";
int countSpaces = s.Count(Char.IsWhiteSpace);
if (countSpaces > 3)
{
int count = 0;
char n;
foreach (char c in s)
{
if (c == ' ') count++;
if (count == 5)
{
n = 'n';
count++;
}
else n = c;
t += n;
}
}
else t = s;
MessageBox.Show(t);
``````

Solution

Using `+=` to concatenate strings in a loop scales very badly. Each iteration creates a new string instance by copying the previous string and the new character into a new string, and that string grows for each iteration. Using a `StringBuilder` (as Dmitry suggests) would be a great improvment.

However, you don’t need to build the string character by character. You could use a regular expression to replace the fifth space with a newline:

``````string t = Regex.Replace(s, "^([^ ]+(?: [^ ]+){4}) ", "\$1" + Environment.NewLine);
``````

Explanation of the pattern:

``````^       mathces the beginning of the string
(       starts a catching group
[^ ]+   matches the first word (a sequence of non-space characters)
(?:     start a non-catching group
space   matches a space
[^ ]+   mathces a word
)       ends the non-catching group
{4}     repeats the group four times
)       ends the catching group
space   matches the fifth space
``````

The `\$1` in the replacement string gets the value caught by the group.

Another alternative would be to loop through the string and look for spaces, then use `Substring` to get the parts before and after the fifth space:

``````int cnt = 0, index = 0;
while (cnt < 5) {
if (s[index++] == ' ') cnt++;
}
string t = s.Substring(0, index - 1) + Environment.NewLine + s.Substring(index);
``````

You could use the `StringBuilder` class and the `String.IndexOf` method as follows:

Option 1

``````private static string ReplaceNthOccurrence(string input, int n, char find, char replaceWith)
{
int index = -1;
int count = 0;
StringBuilder sBuilder = new StringBuilder(input);
while ((index = input.IndexOf(find, index + 1)) != -1)
{
if (++count == n)
{
sBuilder[index] = replaceWith;
break;
}
}
return sBuilder.ToString();
}
``````

Usage:

``````string input = "Hi this is empty string. This should be in new line!";
string output = ReplaceNthOccurrence(input , 5, ' ', 'n');
``````

The `StringBuilder` class allows us to replace a particular `char` in the `string` by its index.
The `String.IndexOf` method allows us to fast search for a desired `char` in the `string`.

Option 2

``````private static string ReplaceNthOccurrence(string input, int n, char find, char replaceWith)
{
int index = -1;
// Loop for `n` occurrences:
for (int count = 0; count < n; count++)
{
// Find a position of the next occurrence:
index = input.IndexOf(find, index + 1);
if (index == -1)
return input;
}
// Replace the char and return a resulting string:
StringBuilder sBuilder = new StringBuilder(input);
sBuilder[index] = replaceWith;
return sBuilder.ToString();
}
``````

In the latter option, you can use any other replacement approach instead of the `StringBuilder`.
For instance:

``````return input.Substring(0, index) + replaceWith + input.Substring(index + 1);
``````