5

I ran visual studio analysis on my code and i found that a large amount of time was spent concatenating strings. Is there a quicker way to concatenate?

    string[] infoseperated = info.Split(' ');   
    for (int iii = totalremove; iii < infoseperated.Length; iii++)
    {
    newinfo += infoseperated[iii] + " ";
    }
2

9 Answers 9

13

use string.Join instead:

newinfo = string.Join(" ", infoseperated.Skip(totalremove));

Your current approach generates a new string for every concatenation (since strings are immutable and you have to re-assign a new string), which is quite expensive.

For every concatenation all characters of the existing string have to be copied into the new string, so the cost of this operation grows with the number of characters in a string - it's a Schlemiel the Painter's algorithm

string.Join uses a StringBuilder internally which avoids this.

Sign up to request clarification or add additional context in comments.

7 Comments

You need infoseparated.Skip(totalremove) to match the semantics of the OP.
@BrokenGlass Skip will have to type-check the array to see whether it implements IList<string>; the Join overload that takes a startindex and a length would probably be more efficient.
@phoog: Perhaps, if you need to squeeze every last ounce of performance out of this. The Skip version is frankly a little more readable, so that's a factor too.
is there a way to use the join so that it has a max limit too? instead of infoseperated.Length a varable total as the max
@Jason I just checked, and the array version of Join allocates one string by calculating the total length needed up front (which means it iterates the array twice), while the IEnumerable version uses a string builder (which means it potentially requires several allocations). So the relative performance will most likely depend on the number of string elements and on their lengths.
|
4

you should take a look at the StringBuilder class. It is meant for things like this.

1 Comment

StringBuilder is good for the general case, but for this specific case String.Join is probably a better choice.
1

Every time you concatenate with the + operator, you're creating a new object. Instead, use the StringBuilder class.

Comments

0

Use System.Text.StringBuilder. It has better performance than string concatenation.

1 Comment

And String.Join is even better because there's less code to write in this case.
0

string.Join, string.Append and string.Format("") are probably more efficient than adding strings, however that doesn't mean that you will necessarily improve your speed as much as you really want to. You should try to look at the big picture and really determine why you're concatenating strings so much, if you can minimize that action then it might be better than just using the most efficient concatenation method.

3 Comments

This is wrong. + compiles to Concat anyway, and Concat suffers from the Schlemiel the Painter problem.
I have removed my downvote since you edited your answer in accordance with my previous comment.
@Jason, thanks... the point of my answer is that using the fastest concatenation method is good, but it's better to eliminate the bottleneck altogether (if possible).
0

Try using StringBuilder:

        StringBuilder sb = new StringBuilder();
        int totalremove = 0;
        string[] infoseperated = info.Split(' ');
        for (int iii = totalremove; iii < infoseperated.Length; iii++)
        {
            sb.Append(infoseperated[iii]);
            sb.Append(" ");
        }
        newinfo = sb.ToString();

Comments

0

Other answers are correct to suggest string.Join, but they are suggesting the wrong overload:

newInfo = string.Join(" ", infoseparated, totalremove, infoseparated.Length - totalremove);

2 Comments

Or you can just use infoseparated.Skip(totalremove) as the second parameter to String.Join.
@Jason true, but the Skip call will have a little more overhead, so if performance is critical, the Join(string, string[], int, int) call may be better.
0

As numerous other answers have said, using a StringBuilder either directly or indirectly through string.Join will be much better performance. However, in your example Split & Join, I think we can do even better.

// first, find the n-th (totalremove-th) separating space.
int index = 0;
for(int i = 0; i < totalremove; i++)
{
    index = infoseperated.IndexOf(' ', index + 1);
    if(index == -1) return ""; // e.g., asked to remove 5 values, but only 3 in the string.
}

// return everything after that point.
return infoseperated.Substring(index + 1);

As long as infoseperated doesn't have any double-spaces, or a space at the beginning, or anything like that, this will be more efficient than splitting & reassembling the string.

Comments

0

If performance is the greatest concern, the fastest method would probably be not to split the string at all and incur no memory allocation overhead except getting the substring;

string newinfo;
while (totalremove-- > 0 && (index = info.IndexOf(' ', index)) >= 0) index+=1;
if (index >= 0)
    newinfo = info.Substring(index);
else
    newinfo = "";

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.