1064

What is the best way to generate a string of \t's in C#?

I am learning C# and experimenting with different ways of saying the same thing.

Tabs(uint t) is a function that returns a string with t amount of \t's

For example, Tabs(3) returns "\t\t\t"

Which of these three ways of implementing Tabs(uint numTabs) is best?

Of course that depends on what "best" means.

  1. The LINQ version is only two lines, which is nice. But are the calls to Repeat and Aggregate unnecessarily time/resource consuming?

  2. The StringBuilder version is very clear, but is the StringBuilder class somehow slower?

  3. The string version is basic, which means it is easy to understand.

  4. Does it not matter at all? Are they all equal?

These are all questions to help me get a better feel for C#.

private string Tabs(uint numTabs) { IEnumerable<string> tabs = Enumerable.Repeat("\t", (int) numTabs); return (numTabs > 0) ? tabs.Aggregate((sum, next) => sum + next) : ""; } private string Tabs(uint numTabs) { StringBuilder sb = new StringBuilder(); for (uint i = 0; i < numTabs; i++) sb.Append("\t"); return sb.ToString(); } private string Tabs(uint numTabs) { string output = ""; for (uint i = 0; i < numTabs; i++) { output += '\t'; } return output; } 
0

23 Answers 23

1934

What about this:

string tabs = new string('\t', n); 

Where n is the number of times you want to repeat the string.

Or better:

static string Tabs(int n) { return new string('\t', n); } 
Sign up to request clarification or add additional context in comments.

4 Comments

is there any way to repeat this for a word? instead of using '\t' how to use "time"
@user1478137 Or, better (also further down): this
When replacing '\t' by a space (ie. " "), I find that on some laptops it is seen as a white space and on some others, a "return key" gets added after the spaces at the end of the line. The other answer suggested here below, that uses string.Concat, also behaves in the same weird way on some laptops. Any idea why this is happening? Thanks
Is there any way to get this as a const? const string a = new string('\t', n) throws a CS0133.
247
string.Concat(Enumerable.Repeat("ab", 2)); 

Returns

"abab"

And

string.Concat(Enumerable.Repeat("a", 2)); 

Returns

"aa"

from...

Is there a built-in function to repeat string or char in .net?

6 Comments

Make it better by doing it without Linq and with StruingBuilder!
''StringBuilder'' is not necessarily faster stackoverflow.com/questions/585860/…
It may not be faster, but it can save on memory allocations (pressure) if you specify the correct capacity up front, and that can be as important as the micro benchmark of profiling this.
var strRepeat = string.Concat(Enumerable.Repeat("ABC", 1000000)); //50ms
How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.
|
159

In all versions of .NET, you can repeat a string thus:

public static string Repeat(string value, int count) { return new StringBuilder(value.Length * count).Insert(0, value, count).ToString(); } 

To repeat a character, new String('\t', count) is your best bet. See the answer by @CMS.

8 Comments

This is by far the fastest performance wise for String. Other methods create too much overhead.
@midspace Do you know if anybody has explained why the other answers are worse? I would have assumed the native String.Concat would be just as optimized internally as StringBuilder
@Marie The following article explains some of the merits. support.microsoft.com/en-au/help/306822/… Otherwise two other factors are, StringBuilder allows strings and isn't limited to just a char (though that doesn't pertain to the original question), and the string.Concat answer above has to create an array first using Enumerable.Repeat. As I said, it's unnecessary overhead.
I had assumed it wouldnt create an array first because it could just iterate item by item. Thank you for the link, I will ggive it a read!
@midspace - your link refers to use of Concat to append strings one at a time. Do you have evidence that Concat(IEnumerable) first makes an array of strings? That would be a very inefficient way to implement a method that takes an Enumerable.
|
70

The best version is certainly to use the builtin way:

string Tabs(int len) { return new string('\t', len); } 

Of the other solutions, prefer the easiest; only if this is proving too slow, strive for a more efficient solution.

If you use a StringBuilder and know its resulting length in advance, then also use an appropriate constructor, this is much more efficient because it means that only one time-consuming allocation takes place, and no unnecessary copying of data. Nonsense: of course the above code is more efficient.

3 Comments

My benchmarks are showing new string('\t', len) to be between 2x and 7x faster than the StringBuilder approach. Why do you think StringBuilder is more efficient in this case?
@StriplingWarrior Thanks for correcting this (after it has been standing here for two years, no less!).
or perhaps that paragraph you struck from your answer was only saying that if you use a StringBuilder, and can compute the needed length ahead of time, and do new StringBuilder(knownLength); then that makes StringBuilder much more efficient. This is a true statement in general; independent of whether in this case the new string answer is even faster. :)
54

Extension methods:

public static string Repeat(this string s, int n) { return new String(Enumerable.Range(0, n).SelectMany(x => s).ToArray()); } public static string Repeat(this char c, int n) { return new String(c, n); } 

4 Comments

Enumerable.Range(0, n).SelectMany(x => s) can be replaced by a simple Enumerable.Repeat(s, n).
@Palec No it cannot. The SelectMany will for each single dummy x give a sequence of char values (since the string s implements IEnumerable<char>), and all those char sequences are concatenated to one long char sequence. What you suggest will instead give an IEnumerable<string>. It is not the same.
I was wrong, @JeppeStigNielsen. Thanks for the heads-up. If I really wanted to use Enumerable.Repeat, I would have to concatenate the strings together: string.Concat(Enumerable.Repeat(s, n)). This has already been posted before.
I find uses of SelectMany that ignore the input parameter x to be less readable / less obvious. I'd go with String.Concat(Repeat(s, n)) instead. Or the StringBuilder answer.
44

Use an extension method:


public static class StringExtensions { public static string Repeat(this char chatToRepeat, int repeat) { return new string(chatToRepeat, repeat); } public static string Repeat(this string stringToRepeat, int repeat) { var builder = new StringBuilder(repeat*stringToRepeat.Length); for (int i = 0; i < repeat; i++) { builder.Append(stringToRepeat); } return builder.ToString(); } } 

You could then write:

Debug.WriteLine('-'.Repeat(100)); // For Chars Debug.WriteLine("Hello".Repeat(100)); // For Strings 

Note that a performance test of using the StringBuilder version for simple characters instead of strings gives you a major performance penality:

On my computer the difference in measured performance is 1:20 between:

Debug.WriteLine('-'.Repeat(1000000)) // Char version 

and

Debug.WriteLine("-".Repeat(1000000)) // String version 

2 Comments

The performance of the string version may be improved by using StringBuilder.Insert(Int32, String, Int32), as Binoj Anthony answered.
I used the code and that was good for me. But the other answers in this q are good too.
28

Let's say you want to repeat '\t' n number of times, you can use;

String.Empty.PadRight(n,'\t') 

2 Comments

Thanks. This is also very fast. codereview.stackexchange.com/questions/36391/…
I have always done it this way. Even if wrapped in an extension method it is simpler than other implementations posted here. Note that OP did just want to repeat \t, not strings.
26

How about this:

//Repeats a character specified number of times public static string Repeat(char character,int numberOfIterations) { return "".PadLeft(numberOfIterations, character); } //Call the Repeat method Console.WriteLine(Repeat('\t',40)); 

1 Comment

haha.. that's what I could think of when I fell into this situation once. But personally I found new string('\t', 10) to be the best solution
26

There is a simple way to repeat a string that even works in .NET 2.0.

To repeat a string:

string repeated = new String('+', 3).Replace("+", "Hello, "); 

Returns

"Hello, Hello, Hello, "

To repeat a string as an array:

// Two line version. string repeated = new String('+', 3).Replace("+", "Hello,"); string[] repeatedArray = repeated.Split(','); // One line version. string[] repeatedArray = new String('+', 3).Replace("+", "Hello,").Split(','); 

Returns

{"Hello", "Hello", "Hello", ""}

Keep it simple.

1 Comment

How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.
19

Your first example which uses Enumerable.Repeat:

private string Tabs(uint numTabs) { IEnumerable<string> tabs = Enumerable.Repeat( "\t", (int) numTabs); return (numTabs > 0) ? tabs.Aggregate((sum, next) => sum + next) : ""; } 

can be rewritten more compactly with String.Concat:

private string Tabs(uint numTabs) { return String.Concat(Enumerable.Repeat("\t", (int) numTabs)); } 

Comments

15

Using String.Concat and Enumerable.Repeat which will be less expensive than using String.Join

public static Repeat(this String pattern, int count) { return String.Concat(Enumerable.Repeat(pattern, count)); } 

1 Comment

Can you quantify that? On a particular system.
8
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray()); 

1 Comment

why additional enumerable when there's same result with: new string('\t', numTabs)
4

The answer really depends on the complexity you want. For example, I want to outline all my indents with a vertical bar, so my indent string is determined as follows:

return new string(Enumerable.Range(0, indentSize*indent).Select( n => n%4 == 0 ? '|' : ' ').ToArray()); 

Comments

4

And yet another method

new System.Text.StringBuilder().Append('\t', 100).ToString() 

1 Comment

Passing the resulting string length to StringBuilder constructor saves reallocation. Still, this is more chatty and less efficient than using the string constructor that can repeat a given character, as already shown in the accepted answer.
4

You can create an extension method

static class MyExtensions { internal static string Repeat(this char c, int n) { return new string(c, n); } } 

Then you can use it like this

Console.WriteLine('\t'.Repeat(10)); 

Comments

4

For me this is fine:

public static class Utils { public static string LeftZerosFormatter(int zeros, int val) { string valstr = val.ToString(); valstr = new string('0', zeros) + valstr; return valstr.Substring(valstr.Length - zeros, zeros); } } 

2 Comments

Fine in what way?
What is it supposed to do? Add leading zeros to a number? How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". And about three specific methods for doing do.
1

Without a doubt the accepted answer is the best and fastest way to repeat a single character.

Binoj Anthony's answer is a simple and quite efficient way to repeat a string.

However, if you don't mind a little more code, you can use my array fill technique to efficiently create these strings even faster. In my comparison tests, the code below executed in about 35% of the time of the StringBuilder.Insert code.

public static string Repeat(this string value, int count) { var values = new char[count * value.Length]; values.Fill(value.ToCharArray()); return new string(values); } public static void Fill<T>(this T[] destinationArray, params T[] value) { if (destinationArray == null) { throw new ArgumentNullException("destinationArray"); } if (value.Length > destinationArray.Length) { throw new ArgumentException("Length of value array must not be more than length of destination"); } // set the initial array value Array.Copy(value, destinationArray, value.Length); int copyLength, nextCopyLength; for (copyLength = value.Length; (nextCopyLength = copyLength << 1) < destinationArray.Length; copyLength = nextCopyLength) { Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength); } Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength); } 

For more about this array fill technique, see Fastest way to fill an array with a single value

Comments

0

Albeit very similar to a previous suggestion, I like to keep it simple and apply the following:

string MyFancyString = "*"; int strLength = 50; System.Console.WriteLine(MyFancyString.PadRight(strLength, "*"); 

It is standard .NET, really.

3 Comments

It will just add padding, does not repeat
@levi: What is the problem with padding? Does string result = string.Empty.PadRight('\t',5) not return the desired result (in this case, 5 tabs)?
How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.
0
string input = "abc" string output = ""; for (int i = 0; i < input.Length; i++) { output += input[i].ToString() + input[i].ToString(); } Console.WriteLine(output); 

Output:

=aabbcc 

1 Comment

How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.
0

In case using spans are an option to be considered here, since the heap allocations will be reduced since we operate on the stack instead, here is a method for also doing char repeats using Span:

void Main() { if (numTabs < 0) { throw new ArgumentException($"{nameof(numTabs)} : Must be a positive number or zero"); } string eightTabs = Tabs(4); Console.WriteLine($"Here is your tabs:{eightTabs} . Did you like them?"); } private string Tabs(int numTabs){ Span<char> span = new Span<char>(new char[numTabs]); var tabSpan = "\t".AsSpan(); for (int i = 0; i < numTabs; i++) { tabSpan.CopyTo(span.Slice(i, 1)); } return span.ToString(); } 

This is however a more complex solution to a very trivial programming task that probably will not need such optimization. But in the case you would repeat tabs several tens of thousands of times, it could have its use.

Comments

0

One example with string extension:

/// <summary> /// Multiply text x times and return it as string array /// if merge enabled, merge array items in to one string /// <code> /// @example /// var arr = "ab".Repeat(3, false); > out: {"ab", "ab", "ab"}; /// var str = "ab".Repeat(3, true)[0]; > out: "ababab"; /// </code> /// </summary> public static string[] Repeat(this string str, int count, bool merge) { return merge ? new string[] { string.Concat(Enumerable.Repeat(str, count)) } : Enumerable.Repeat(str, count).ToArray(); } 

Comments

-1

Try this:

  1. Add the Microsoft.VisualBasic reference
  2. Use: String result = Microsoft.VisualBasic.Strings.StrDup(5, "hi");

3 Comments

Adding dependence on another assembly and the need to load it is unreasonable in most cases when you need such functionality. Still, good to know there is such a thing in .NET.
There many pros and cons in different contexts, so everyone should decide depending on the situation she/he is in.
How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.
-4

Fill the screen with 6,435 z's:

$str = [System.Linq.Enumerable]::Repeat([string]::new("z", 143), 45) $str 

2 Comments

What is this? PowerShell? That is hardly C#.
How does that answer the question? It was "What is the best way to generate a string of \t's in C#?". A question is more than the title. And about three specific methods for doing do.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.