365

I'm trying to insert a certain number of indentations before a string based on an items depth and I'm wondering if there is a way to return a string repeated X times. Example:

string indent = "---";
Console.WriteLine(indent.Repeat(0)); //would print nothing.
Console.WriteLine(indent.Repeat(1)); //would print "---".
Console.WriteLine(indent.Repeat(2)); //would print "------".
Console.WriteLine(indent.Repeat(3)); //would print "---------".
Steve Townsend
  • 51,210
  • 8
  • 87
  • 134
Abe Miessler
  • 75,910
  • 89
  • 276
  • 451
  • 9
    Not sure if this is applicable, but you might want to look at the [IndentedTextWriter](http://msdn.microsoft.com/en-us/library/system.codedom.compiler.indentedtextwriter%28v=VS.100%29.aspx) as well. – Chris Shouts Sep 20 '10 at 19:09

20 Answers20

622

If you only intend to repeat the same character you can use the string constructor that accepts a char and the number of times to repeat it new String(char c, int count).

For example, to repeat a dash five times:

string result = new String('-', 5);
Output: -----
live2
  • 2,620
  • 2
  • 25
  • 35
Ahmad Mageed
  • 88,056
  • 18
  • 152
  • 168
  • 9
    Thanks for reminding me about this nice little feature. I think it was lost in the corner of my mind. – Chris Shouts Sep 20 '10 at 19:18
  • 3
    Since the tab metacharacter '\t' is a char this works for indentation as well. – cori Dec 14 '12 at 18:26
  • 94
    This is a very useful trick of C#, but the title of the question is asking about a string (not a char). The other answers below this one are actually answering the question, but are rated much lower. I'm not trying to disrespect Ahmad's answer, but I think either the title of this question should be changed (if the question is actually regarding characters) or the other answers really should be upvoted (and not this one). – pghprogrammer4 Mar 13 '13 at 16:16
  • 15
    @Ahmad As I said, I did not downvote because I don't think you provided good information, but because the information you provided is not relevant to answering the question _as currently stated_. Imagine if you were searching for a way to repeat strings (not chars) and when you get to the relevant question you have to scroll through several 'useful' tips to get to the actual answers to the question. If the downvote is offense to you, I can remove it. But do you see where I'm coming from? Am I totally off-base here? – pghprogrammer4 Mar 13 '13 at 16:42
  • 12
    @pghprogrammer4 IMHO, downvotes can be quite discouraging, and should only be used for harmful/misleading/truly_bad answers, that need a major change or should be deleted by their author. Answers exist because people are generous and wish to share what they know. Generally, these sites really on the encouragement of upvotes to bring useful answers to the top. – ToolmakerSteve Mar 18 '14 at 04:17
  • 1
    Great. Faster and smaller than others answers below. thanks. – Andre Mesquita Nov 01 '18 at 03:37
  • 1
    This does not answer the question. I need to repeat a string. Not one single char. – Tvde1 Jun 21 '19 at 19:25
298

If you're using .NET 4.0, you could use string.Concat together with Enumerable.Repeat.

int N = 5; // or whatever
Console.WriteLine(string.Concat(Enumerable.Repeat(indent, N)));

Otherwise I'd go with something like Adam's answer.

The reason I generally wouldn't advise using Andrey's answer is simply that the ToArray() call introduces superfluous overhead that is avoided with the StringBuilder approach suggested by Adam. That said, at least it works without requiring .NET 4.0; and it's quick and easy (and isn't going to kill you if efficiency isn't too much of a concern).

Community
  • 1
  • 1
Dan Tao
  • 119,009
  • 50
  • 280
  • 431
  • 3
    This will work nicely with strings - like if you need to concat non-breaking spaces ( ). But I assume the string constructor will be fastest if you're dealing with a char... – woodbase Sep 12 '12 at 11:52
  • 1
    String constructor will only work for one char. to option of using Concat Repeat will work for strings – Eli Dagan Dec 12 '16 at 10:00
  • 4
    Thanks for answering the actual title question! – Mark K Cowan Dec 16 '16 at 03:24
  • I like this answer! – Ji_in_coding Aug 22 '17 at 15:01
  • If you are getting -System.Linq.Enumerable etc as output, it's because you (ok, this was me) were too quick to copy/paste and modify the snippet. If you need to concat a different string onto the output of the Enumerable.Repeat, you need to do it like this: `Console.WriteLine(string.Concat("-", string.Concat(Enumerable.Repeat(indent, N))));` – Gabe Feb 11 '20 at 14:22
55

most performant solution for string

string result = new StringBuilder().Insert(0, "---", 5).ToString();
c0rd
  • 1,059
  • 1
  • 9
  • 18
  • 4
    Sure is a pretty one-liner. Sure not the most performant. StringBuilder has a little overhead over very little number of concatenations. – Teejay Mar 26 '18 at 10:26
48
public static class StringExtensions
{
    public static string Repeat(this string input, int count)
    {
        if (!string.IsNullOrEmpty(input))
        {
            StringBuilder builder = new StringBuilder(input.Length * count);

            for(int i = 0; i < count; i++) builder.Append(input);

            return builder.ToString();
        }

        return string.Empty;
    }
}
Adam Robinson
  • 171,726
  • 31
  • 271
  • 330
  • 7
    Might as well pass `input.Length * count` to the `StringBuilder` constructor, don't you think? – Dan Tao Sep 20 '10 at 19:16
  • Adam, I see you went to the trouble of testing input for null when adding it to count, but then allowed that to fall through, relying on Append to do nothing given the null. IMHO this is less than obvious: if null is a possible input, why not test for that up front, and return an empty string? – ToolmakerSteve Mar 18 '14 at 04:33
  • 2
    @AdamRobinson Is returning an empty string in place of a null desirable? I'd replace `return string.empty` with `return input`, that way you get null in/null out, and empty in/empty out. – MattDavey Nov 07 '17 at 12:53
  • Need to check `count > 0` or constructing `StringBuilder` will throw an exception. – Roger Stewart Apr 10 '18 at 16:09
30

For many scenarios, this is probably the neatest solution:

public static class StringExtensions
{
    public static string Repeat(this string s, int n)
        => new StringBuilder(s.Length * n).Insert(0, s, n).ToString();
}

Usage is then:

text = "Hello World! ".Repeat(5);

This builds on other answers (particularly @c0rd's). As well as simplicity, it has the following features, which not all the other techniques discussed share:

  • Repetition of a string of any length, not just a character (as requested by the OP).
  • Efficient use of StringBuilder through storage preallocation.
Bob Sammers
  • 2,501
  • 23
  • 30
22

Use String.PadLeft, if your desired string contains only a single char.

public static string Indent(int count, char pad)
{
    return String.Empty.PadLeft(count, pad);
}

Credit due here

Steve Townsend
  • 51,210
  • 8
  • 87
  • 134
  • 1
    KISS. What do we need StringBuilders and extensions for, anyway? This is a very simple problem. – DOK Sep 20 '10 at 19:16
  • 1
    I dunno, this seems to solve the problem as phrased with some elegance. And btw, who are you calling 'S'? :-) – Steve Townsend Sep 20 '10 at 19:20
  • 9
    But isn't this really just a less obvious version of [the `string` constructor that takes a `char` and an `int`](http://msdn.microsoft.com/en-us/library/xsa4321w.aspx)? – Dan Tao Sep 20 '10 at 19:26
  • It would look nicer with String.Empty instead of ""... otherwise, good solution ;) – Thomas Levesque Sep 20 '10 at 19:26
  • @Steve BTW the [`String.PadLeft`](http://msdn.microsoft.com/en-us/library/92h5dc07.aspx) arguments are reversed. The `count` comes before the padding character. – Ahmad Mageed Sep 20 '10 at 19:32
19

You can repeat your string (in case it's not a single char) and concat the result, like this:

String.Concat(Enumerable.Repeat("---", 5))
LiRoN
  • 642
  • 5
  • 9
11

I would go for Dan Tao's answer, but if you're not using .NET 4.0 you can do something like that:

public static string Repeat(this string str, int count)
{
    return Enumerable.Repeat(str, count)
                     .Aggregate(
                        new StringBuilder(str.Length * count),
                        (sb, s) => sb.Append(s))
                     .ToString();
}
Thomas Levesque
  • 270,447
  • 59
  • 580
  • 726
6

Works with strings and chars:

Strings and chars [version 1]

string.Join("", Enumerable.Repeat("text" , 2 ));    
//result: texttext

Strings [version 2]:

String.Concat(Enumerable.Repeat("text", 2));
//result: texttext

Strings and chars [version 3]

new StringBuilder().Insert(0, "text", 2).ToString(); 
//result: texttext

Chars only:

'5' * 3; 
//result: 555

Extension way:

(works FASTER - better for WEB)

public static class RepeatExtensions
{
    public static string Repeat(this string str, int times)
    {
        return (new StringBuilder()).Insert(0, str, times).ToString();
    }
}

usage:

 var a = "Hello".Repeat(3); 
 //result: HelloHelloHello
stomy
  • 871
  • 11
  • 14
Andrew
  • 5,048
  • 4
  • 35
  • 58
  • Yours should be the accepted answer. Here is a nice usage in Html: var indents = string.Join("", Enumerable.Repeat(" ", Tabs * 3)); – John Ernest Dec 31 '20 at 07:14
  • 1
    @JohnErnest for web better to use extension that I have added right now. I have write it because of insertion is relatively long operation than appending – Andrew Dec 31 '20 at 11:16
  • my use case was writing a simple Roslyn CSharpSyntaxWalker for a SyntaxTree in a browser window, neither tabs or spaces by themselves would indent, unless I had used a CSS rule. – John Ernest Dec 31 '20 at 21:58
  • `RepeatAction` seems like an unnecessary obscure way to do `for`. – NetMage Jan 11 '21 at 23:38
  • yes and no both. Using this you can do RepeatAction in another places without for syntax. :) This is also useful in code. Not only at this place. – Andrew Jan 12 '21 at 14:15
4
        string indent = "---";
        string n = string.Concat(Enumerable.Repeat(indent, 1).ToArray());
        string n = string.Concat(Enumerable.Repeat(indent, 2).ToArray());
        string n = string.Concat(Enumerable.Repeat(indent, 3).ToArray());
Andrey
  • 56,384
  • 10
  • 111
  • 154
2

I like the answer given. Along the same lines though is what I've used in the past:

"".PadLeft(3*Indent,'-')

This will fulfill creating an indent but technically the question was to repeat a string. If the string indent is something like >-< then this as well as the accepted answer would not work. In this case, c0rd's solution using StringBuilder looks good, though the overhead of StringBuilder may in fact not make it the most performant. One option is to build an array of strings, fill it with indent strings, then concat that. To whit:

int Indent = 2;
        
string[] sarray = new string[6];  //assuming max of 6 levels of indent, 0 based

for (int iter = 0; iter < 6; iter++)
{
    //using c0rd's stringbuilder concept, insert ABC as the indent characters to demonstrate any string can be used
    sarray[iter] = new StringBuilder().Insert(0, "ABC", iter).ToString();
}

Console.WriteLine(sarray[Indent] +"blah");  //now pretend to output some indented line

We all love a clever solution but sometimes simple is best.

Pang
  • 8,605
  • 144
  • 77
  • 113
1

Another approach is to consider string as IEnumerable<char> and have a generic extension method which will multiply the items in a collection by the specified factor.

public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int times)
{
    source = source.ToArray();
    return Enumerable.Range(0, times).SelectMany(_ => source);
}

So in your case:

string indent = "---";
var f = string.Concat(indent.Repeat(0)); //.NET 4 required
//or
var g = new string(indent.Repeat(5).ToArray());
nawfal
  • 62,042
  • 48
  • 302
  • 339
1

Surprised nobody went old-school. I am not making any claims about this code, but just for fun:

public static string Repeat(this string @this, int count)
{
    var dest = new char[@this.Length * count];
    for (int i = 0; i < dest.Length; i += 1)
    {
        dest[i] = @this[i % @this.Length];
    }
    return new string(dest);
}
OlduwanSteve
  • 1,171
  • 13
  • 16
  • *Obviously* I left that in as a test for the astute reader :) Very astute, thanks. – OlduwanSteve Oct 14 '13 at 15:37
  • 1
    There's nothing old-school about naming a parameter @this, that's always been a horrible idea :) – Dave Jellison Nov 05 '13 at 05:12
  • Even in the context of an extension method? It seems reasonable when @this is indeed.. 'this' but I'm always open to being swayed. Is that an aesthetic judgement or is there a practical downside? – OlduwanSteve Nov 05 '13 at 11:11
  • 2
    I prefer not to use keyword as variable names unless forced (such as @class = "something" when working with MVC because you need class referring to CSS but it's a keyword in C# (of course). This isn't just me talking, it's a general rule of thumb. Although it's certainly compilable code and legitimate, think about ease of reading and typing as well, both practical reasons. I'm very partial to using parameter names to describe what's happening first so Repeat(this string seed, int count) might be more illustrative imho. – Dave Jellison Nov 07 '13 at 04:45
  • 1
    Interesting, thanks. I think in this case you're probably right that @this is less descriptive than it could be. However in general I think it is quite common to be extending classes or interfaces where the only reasonable name for 'this' is rather generic. If you have a parameter called 'instance' or 'it' or 'str' (see [MSDN](http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx)) then what you probably meant is 'this'. – OlduwanSteve Nov 07 '13 at 13:00
  • Oh I agree, I always end up pausing on these methods to think of something useful. When I can't, I typically go with "value" as the parameter name, at least it saves me the carpal on one extra @ symbol to type. I really do think the readability of code is improved any time you can keep the symbols to code features and your primary language only in class, property, variable, etc. naming personally. – Dave Jellison Nov 07 '13 at 23:45
  • Maybe nobody went old school because that's what StringBuilder is for ;P – ToolmakerSteve Mar 18 '14 at 04:29
  • 1
    I basically agree with you, but for the sake of argument... since I know more about the string I'm building I can do a marginally better job than StringBuilder. StringBuilder has to make a guess when it's allocating memory. Granted it's unlikely to matter in many scenarios, but somebody out there might be building an enormous number of repeated strings in parallel and be glad to gain a few clock cycles back :) – OlduwanSteve Mar 18 '14 at 11:37
1

Not sure how this would perform, but it's an easy piece of code. (I have probably made it appear more complicated than it is.)

int indentCount = 3;
string indent = "---";
string stringToBeIndented = "Blah";
// Need dummy char NOT in stringToBeIndented - vertical tab, anyone?
char dummy = '\v';
stringToBeIndented.PadLeft(stringToBeIndented.Length + indentCount, dummy).Replace(dummy.ToString(), indent);

Alternatively, if you know the maximum number of levels you can expect, you could just declare an array and index into it. You would probably want to make this array static or a constant.

string[] indents = new string[4] { "", indent, indent.Replace("-", "--"), indent.Replace("-", "---"), indent.Replace("-", "----") };
output = indents[indentCount] + stringToBeIndented;      
B H
  • 1,376
  • 16
  • 21
1

I don't have enough rep to comment on Adam's answer, but the best way to do it imo is like this:

public static string RepeatString(string content, int numTimes) {
        if(!string.IsNullOrEmpty(content) && numTimes > 0) {
            StringBuilder builder = new StringBuilder(content.Length * numTimes);

            for(int i = 0; i < numTimes; i++) builder.Append(content);

            return builder.ToString();
        }

        return string.Empty;
    }

You must check to see if numTimes is greater then zero, otherwise you will get an exception.

Gru
  • 363
  • 2
  • 8
1

Print a line with repetition.

Console.Write(new string('=', 30) + "\n");

==============================

Kamal
  • 341
  • 1
  • 7
  • 18
1

For general use, solutions involving the StringBuilder class are best for repeating multi-character strings. It's optimized to handle the combination of large numbers of strings in a way that simple concatenation can't and that would be difficult or impossible to do more efficiently by hand. The StringBuilder solutions shown here use O(N) iterations to complete, a flat rate proportional to the number of times it is repeated.

However, for very large number of repeats, or where high levels of efficiency must be squeezed out of it, a better approach is to do something similar to StringBuilder's basic functionality but to produce additional copies from the destination, rather than from the original string, as below.

    public static string Repeat_CharArray_LogN(this string str, int times)
    {
        int limit = (int)Math.Log(times, 2);
        char[] buffer = new char[str.Length * times];
        int width = str.Length;
        Array.Copy(str.ToCharArray(), buffer, width);

        for (int index = 0; index < limit; index++)
        {
            Array.Copy(buffer, 0, buffer, width, width);
            width *= 2;
        }
        Array.Copy(buffer, 0, buffer, width, str.Length * times - width);

        return new string(buffer);
    }

This doubles the length of the source/destination string with each iteration, which saves the overhead of resetting counters each time it would go through the original string, instead smoothly reading through and copying the now much longer string, something that modern processors can do much more efficiently.

It uses a base-2 logarithm to find how many times it needs to double the length of the string and then proceeds to do so that many times. Since the remainder to be copied is now less than the total length it is copying from, it can then simply copy a subset of what it has already generated.

I have used the Array.Copy() method over the use of StringBuilder, as a copying of the content of the StringBuilder into itself would have the overhead of producing a new string with that content with each iteration. Array.Copy() avoids this, while still operating with an extremely high rate of efficiency.

This solution takes O(1 + log N) iterations to complete, a rate that increases logarithmically with the number of repeats (doubling the number of repeats equals one additional iteration), a substantial savings over the other methods, which increase proportionally.

buchWyrm
  • 107
  • 9
1

Adding the Extension Method I am using all over my projects:

public static string Repeat(this string text, int count)
{
    if (!String.IsNullOrEmpty(text))
    {
        return String.Concat(Enumerable.Repeat(text, count));
    }
    return "";
}

Hope someone can take use of it...

Mayer Spitzer
  • 1,791
  • 12
  • 22
0

I didn't see this solution. I find it simpler for where I currently am in software development:

public static void PrintFigure(int shapeSize)
{
    string figure = "\\/";
    for (int loopTwo = 1; loopTwo <= shapeSize - 1; loopTwo++)
    {
        Console.Write($"{figure}");
    }
}
Nelly
  • 17
  • 3
-2

You can create an ExtensionMethod to do that!

public static class StringExtension
{
  public static string Repeat(this string str, int count)
  {
    string ret = "";

    for (var x = 0; x < count; x++)
    {
      ret += str;
    }

    return ret;
  }
}

Or using @Dan Tao solution:

public static class StringExtension
{
  public static string Repeat(this string str, int count)
  {
    if (count == 0)
      return "";

    return string.Concat(Enumerable.Repeat(indent, N))
  }
}
Zote
  • 5,255
  • 5
  • 39
  • 43