我试图根据项目深度在字符串之前插入一定数量的缩进,并且我想知道是否有办法返回重复X次的字符串。示例:

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 "---------".


评论

不知道这是否适用,但是您可能也想看看IndentedTextWriter。

#1 楼

如果只打算重复相同的字符,则可以使用接受char的字符串构造函数,并使用重复次数new String(char c, int count)。 >
string result = new String('-', 5);
Output: -----


评论


感谢您提醒我有关此出色的小功能。我认为它迷失在我的脑海。

–克里斯·呼特斯(Chris Shouts)
2010-09-20 19:18

由于制表符元字符'\ t'是一个字符,因此也适用于缩进。

–科里
2012-12-14 18:26

这是C#的一个非常有用的技巧,但是问题的标题是询问字符串(不是char)。这个答案下面的其他答案实际上是在回答这个问题,但评级要低得多。我并不是想不尊重艾哈迈德的回答,但我认为应该改变这个问题的标题(如果问题实际上是关于字符的),或者真的应该对其他答案进行投票(而不是这个)。

– pghprogrammer4
2013年3月13日16:16



@Ahmad正如我说的那样,我之所以投票不是因为我不认为您提供的信息不错,而是因为您提供的信息与回答当前所说的问题无关。想象一下,如果您正在寻找一种重复字符串(而不是字符)的方法,并且当您遇到相关问题时,您必须滚动浏览几个“有用的”提示以获取问题的实际答案。如果反对票对您不利,我可以将其删除。但是你看到我来自哪里吗?我在这里完全是基地吗?

– pghprogrammer4
13年13月13日在16:42

@ pghprogrammer4恕我直言,downvotes可能非常令人沮丧,只应用于有害/误导/ truly_bad的答案,需要进行重大更改或应由其作者删除。之所以存在答案,是因为人们慷慨大方并希望分享自己的知识。通常,这些站点实际上是在鼓励投票的前提下,将有用的答案带到顶部。

–ToolmakerSteve
2014年3月18日4:17



#2 楼

如果您使用的是.NET 4.0,则可以将string.ConcatEnumerable.Repeat结合使用。 br />我通常不建议使用Andrey的答案的原因是,ToArray()调用引入了多余的开销,而Adam建议的StringBuilder方法可以避免这种开销。就是说,至少它不需要.NET 4.0就可以工作;而且它既快捷又容易(如果效率不是您所关注的重点,那也不会杀死您)。

评论


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



字符串构造函数仅适用于一个字符。使用Concat Repeat的选项将适用于字符串

– Eli Dagan
16年12月12日10:00

感谢您回答实际标题问题!

– Mark K Cowan
16 Dec 16'3:24

我喜欢这个答案!

– Ji_in_coding
17年8月22日在15:01

如果您获得-System.Linq.Enumerable等作为输出,那是因为您(好吧,这是我)太快地无法复制/粘贴和修改代码段。如果需要将另一个字符串连接到Enumerable.Repeat的输出上,则需要这样做:Console.WriteLine(string.Concat(“-”,string.Concat(Enumerable.Repeat(indent,N))) ));

–加布
20-2-11在14:22



#3 楼

最有效的字符串解决方案

string result = new StringBuilder().Insert(0, "---", 5).ToString();


评论


当然可以。当然不是最出色的。 StringBuilder在很少数量的串联中有一些开销。

– Teejay
18 Mar 26 '18在10:26

#4 楼

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;
    }
}


评论


最好将input.Length *传递给StringBuilder构造函数,您不觉得吗?

–丹涛
2010-09-20 19:16

亚当,我看到您在将输入加到count上时测试了输入是否为空的麻烦,但是后来让它落空了,依靠Append在给出空值的情况下什么也不做。恕我直言,这不是很明显:如果可能为null,为什么不先进行测试,然后返回空字符串?

–ToolmakerSteve
2014年3月18日下午4:33

@AdamRobinson是否需要返回一个空字符串代替null?我用return输入替换return string.empty,这样您就可以得到null in / null out和empty in / empty out。

–马特·戴维(MattDavey)
17年11月7日在12:53



需要检查count> 0或构造StringBuilder会引发异常。

–罗杰·斯图尔特
18年4月10日在16:09

#5 楼

在许多情况下,这可能是最简洁的解决方案:

基于其他答案(尤其是@ c0rd的答案)。除了简单之外,它还具有以下功能,并非所有其他讨论的技术都具有以下功能: )。
通过存储预分配有效地使用StringBuilder


评论


我同意,这太好了。我刚刚将这添加到我的代码中,感谢Bob!谢谢!

–约翰·伯利(John Burley)
'18 -10-31在18:21

#6 楼

如果所需的字符串仅包含一个字符,请使用String.PadLeft。

评论


吻。无论如何,我们需要StringBuilders和扩展用于什么?这是一个非常简单的问题。

– DOK
2010-09-20 19:16



我不知道,这似乎以某种优雅的方式解决了这个问题。顺便说一句,你叫谁“ S”? :-)

–史蒂夫·汤森(Steve Townsend)
2010-09-20 19:20

但是,这难道不是只是一个不太明显的采用char和int的字符串构造函数版本吗?

–丹涛
2010-09-20 19:26

用String.Empty代替“”会更好,否则,很好的解决方案;)

–托马斯·莱维斯克
2010-09-20 19:26

@Steve BTW String.PadLeft参数是相反的。计数位于填充字符之前。

–艾哈迈德(Ahmad Mageed)
2010-09-20 19:32



#7 楼

您可以重复您的字符串(以防它不是单个字符)并合并结果,如下所示:

String.Concat(Enumerable.Repeat("---", 5))


#8 楼

我会寻求Dan Tao的答案,但如果您不使用.NET 4.0,则可以执行以下操作:

public static string Repeat(this string str, int count)
{
    return Enumerable.Repeat(str, count)
                     .Aggregate(
                        new StringBuilder(),
                        (sb, s) => sb.Append(s))
                     .ToString();
}


评论


如果在我的项目中找到此代码段,我会怀疑谁一直在违反KISS,为什么...否则会很好

– Noctis
2014年8月12日在5:24

#9 楼

        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());


评论


@Adam:我想您需要在.NET 4.0之前执行该操作。

–丹涛
2010-09-20 19:11

#10 楼

我喜欢给出的答案。我沿用了过去的用法:
"".PadLeft(3*Indent,'-')

创建缩进可以实现,但是从技术上讲,问题是重复字符串。如果字符串缩进是>-<之类的东西,那么该字符串以及已接受的答案将不起作用。在这种情况下,使用StringBuilder的c0rd解决方案看起来不错,尽管StringBuilder的开销实际上可能无法使其表现最佳。一种选择是建立一个字符串数组,用缩进字符串填充它,然后合并。来看看:
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

我们都喜欢一个聪明的解决方案,但有时候简单是最好的。

#11 楼

另一种方法是将string视为IEnumerable<char>,并具有通用的扩展方法,该方法会将集合中的项乘以指定的因子。 br />
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int times)
{
    source = source.ToArray();
    return Enumerable.Range(0, times).SelectMany(_ => source);
}


#12 楼

惊讶的是没人上过老派。我并未对此代码提出任何要求,只是为了好玩:

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
13年10月14日在15:37

命名参数@this并没有什么老套,这一直是一个可怕的主意:)

–戴夫·杰里森
13年5月5日在5:12

我宁愿不要将关键字用作变量名,除非强制使用(例如@class =“ something”在使用MVC时,因为您需要引用CSS的类,但这是C#中的关键字(当然)。这是一般的经验法则。尽管它当然是可编译的代码,而且合法,但考虑到易于阅读和键入的原因,这两个实际原因都非常有用。 int count)可能是更具说明性的恕我直言。

–戴夫·杰里森
13年7月7日在4:45

有趣,谢谢。我认为在这种情况下,@ this的描述性可能不那么正确。但是总的来说,我认为扩展类或接口是很普遍的,因为“ this”的唯一合理名称是通用的。如果您有一个名为'instance'或'it'或'str'的参数(请参阅MSDN),那么您可能的意思是'this'。

– OlduwanSteve
13年11月7日13:00

我基本上同意您的观点,但是为了争辩……因为我对我正在构建的字符串了解更多,所以我可以比StringBuilder做得更好。 StringBuilder必须在分配内存时进行猜测。当然,在许多情况下这无关紧要,但是有人可能并行构建大量重复的字符串,并且很高兴获得一些时钟周期:)

– OlduwanSteve
2014年3月18日在11:37

#13 楼

不知道这将如何执行,但这是一段简单的代码。 (我可能已经使它看起来比实际要复杂。)或者,如果您知道可以期望的最大级别,则可以声明一个数组并对其进行索引。您可能希望将此数组设为静态或常量。

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);


#14 楼

我没有足够的代表评论亚当的答案,但是imo的最佳方法是这样的:大于零,否则将出现异常。

#15 楼

打印重复行。

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



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


评论


为什么不使用Console.WriteLine而不是在字符串末尾附加\ n呢?

– InxaneNinja
20年5月9日,12:30

#16 楼

对于一般用途,涉及StringBuilder类的解决方案最适合重复多字符字符串。它经过优化,可以处理简单的串联操作无法处理的大量字符串的组合,而这将很难或不可能手动完成。此处显示的StringBuilder解决方案使用O(N)迭代来完成,其固定比率与重复次数成正比。

但是,对于大量重复或效率很高的情况必须将其压缩掉,更好的方法是执行类似于StringBuilder的基本功能,但要从目标而不是从原始字符串生成附加副本,如下所示。

    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);
    }
>
这样每次迭代都会使源/目标字符串的长度加倍,从而节省了每次遍历原始字符串时重置计数器的开销,而无需平滑地读取并复制现在更长的字符串,这使得现代处理器可以提高效率。

它使用以2为底的对数来查找将字符串长度加倍所需的次数,然后进行多次。由于要复制的其余部分现在小于要复制的总长度,因此它可以简单地复制已生成的内容的子集。

我使用了Array.Copy()方法与StringBuilder的使用相比,将StringBuilder的内容复制到自身中会产生开销,每次迭代都会产生一个包含该内容的新字符串。 Array.Copy()避免了这种情况,同时仍然以极高的效率运行。重复(重复次数加倍等于一个额外的迭代),与其他方法相比可节省很多,并且成比例地增加。

#17 楼

添加扩展方法我正在使用我的所有项目:

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


希望有人可以使用它...

#18 楼

适用于字符串和字符:
//Strings and chars ver 1
string.Join("", Enumerable.Repeat("text" , 2 ));    //result: texttext

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

// Chars only:
'5' * 3; //result: 555


扩展方式:
public static class RepeatExtensions
{
    //extension with owerride Multiply is impossible so...
    //also works faster than .Insert(0,x,y) - may be important for web
    public static string Repeat(this string str, int times)
    {
        var a = new StringBuilder();

        ( () => a.Append(str) ).RepeatAction(times) ;
        
        return a.ToString();
    }

    public static void RepeatAction(this Action action, int count)
    {
        for (int i = 0; i < count; i++)
        {
            action();
        }
    }
}

 var a = "Hello".Repeat(3); //result: HelloHelloHello


评论


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 7:14

@JohnErnest可以更好地使用我现在添加的扩展名。我写它是因为插入操作比追加操作要长

–安德鲁(Andrew)
20/12/31在11:16



我的用例是在浏览器窗口中为SyntaxTree编写一个简单的Roslyn CSharpSyntaxWalker,除非我使用CSS规则,否则制表符或空格都不会缩进。

–约翰·欧内斯特(John Ernest)
20 Dec 31 '21:58

#19 楼

我没有看到这个解决方案。对于目前在软件开发中的位置,我发现它更简单:

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


#20 楼

您可以创建一个ExtensionMethod来实现!

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;
  }
}


或使用@Dan Tao解决方案:

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

    return string.Concat(Enumerable.Repeat(indent, N))
  }
}


评论


看到我对凯尔答案的评论

–托马斯·莱维斯克
2010-09-20 19:25

如果使用StringBuilder而不是String,将是一个很好且快速的答案。但是目前,它是不好的。

–安德鲁(Andrew)
20/12/31在12:24