patterncsharpModerate
Expanding a string to a certain length
Viewed 0 times
lengthcertainstringexpanding
Problem
I wrote a function for repeating a string to a certain length.
For example:
Are there any optimizations or fixes that can be done to this function?
For example:
ExpandString("Test", 11);
// output: "TestTestTes"Are there any optimizations or fixes that can be done to this function?
private string ExpandString(string str, int length)
{
if (length <= str.Length) return str.Substring(0, length);
var result = str;
for (var i = str.Length; i < length; i++)
{
result += str[i % str.Length];
}
return result;
}Solution
OK, first, for the most straightforward optimization. Use a StringBuilder.
The way your code currently works, it creates
If you use a StringBuilder instead, you can avoid most of those copies.
You could try something like...
(I don't particularly like the StringBuilder starting with a copy of
But you're also copying one character at a time. While this isn't as big an issue as the concatenation, you can do better by inserting as many whole copies of
Note that the short-string optimization has been removed. You can add it back in if you really really want to micro-optimize, but at this point, it's not gaining you nearly as much as it was.
The way your code currently works, it creates
length - str.Length intermediate strings. Besides creating lots of unnecessary garbage, you're copying longer and longer strings over and over again to add one character each time.If you use a StringBuilder instead, you can avoid most of those copies.
You could try something like...
using System.Text;
...
private string ExpandString(string str, int length)
{
if (length <= str.Length) return str.Substring(0, length);
var result = new StringBuilder(str);
for (var i = str.Length; i < length; i++)
{
result.Append(str[i % str.Length]);
}
return result.ToString();
}(I don't particularly like the StringBuilder starting with a copy of
str already in it. I'm literally just replacing the String.)But you're also copying one character at a time. While this isn't as big an issue as the concatenation, you can do better by inserting as many whole copies of
str as you can.private string ExpandString(string str, int length)
{
// BTW, you already know how big the result should be, so just
// tell the StringBuilder its capacity to prevent unneeded resizes.
// Side benefit: if the result is too long, you'll find out fairly quickly.
var result = new StringBuilder(length, length);
var wholeCopies = length / str.Length;
for (var i = 0; i < wholeCopies; ++i)
{
result.Append(str);
}
// now append the last chunk, a possibly-zero-length prefix of `str`
result.Append(str, 0, length % str.Length);
return result.ToString();
}Note that the short-string optimization has been removed. You can add it back in if you really really want to micro-optimize, but at this point, it's not gaining you nearly as much as it was.
Code Snippets
using System.Text;
...
private string ExpandString(string str, int length)
{
if (length <= str.Length) return str.Substring(0, length);
var result = new StringBuilder(str);
for (var i = str.Length; i < length; i++)
{
result.Append(str[i % str.Length]);
}
return result.ToString();
}private string ExpandString(string str, int length)
{
// BTW, you already know how big the result should be, so just
// tell the StringBuilder its capacity to prevent unneeded resizes.
// Side benefit: if the result is too long, you'll find out fairly quickly.
var result = new StringBuilder(length, length);
var wholeCopies = length / str.Length;
for (var i = 0; i < wholeCopies; ++i)
{
result.Append(str);
}
// now append the last chunk, a possibly-zero-length prefix of `str`
result.Append(str, 0, length % str.Length);
return result.ToString();
}Context
StackExchange Code Review Q#90220, answer score: 12
Revisions (0)
No revisions yet.