【问题标题】:Is there an easy way to return a string repeated X number of times?有没有一种简单的方法可以返回重复 X 次的字符串?
【发布时间】:2011-04-14 20:26:16
【问题描述】:

我正在尝试根据项目深度在字符串之前插入一定数量的缩进,我想知道是否有办法返回重复 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 "---------".

【问题讨论】:

标签: c# .net


【解决方案1】:

如果您只打算重复相同的字符,您可以使用接受字符的string constructor 和重复次数new String(char c, int count)

例如,重复五次破折号:

string result = new String('-', 5);
Output: -----

【讨论】:

  • 感谢您提醒我这个不错的小功能。我想它已经在我的脑海中消失了。
  • 由于制表符元字符 '\t' 是一个字符,它也适用于缩进。
  • 这是一个非常有用的C#技巧,但问题的标题是询问一个字符串(不是字符)。此答案下方的其他答案实际上是在回答问题,但评分要低得多。我并不是想不尊重艾哈迈德的回答,但我认为要么应该更改这个问题的标题(如果问题实际上是关于角色的),要么真的应该支持其他答案(而不是这个)。
  • @Ahmad 正如我所说,我没有投反对票,因为我认为您提供的信息不是很好,而是因为您提供的信息与回答问题无关如目前所述我>。想象一下,如果您正在寻找一种重复字符串(而不是字符)的方法,并且当您遇到相关问题时,您必须滚动浏览几个“有用的”提示才能获得问题的实际答案。如果不赞成投票对您不利,我可以将其删除。但是你知道我从哪里来吗?我在这里完全不在基地吗?
  • @pghprogrammer4 恕我直言,downvotes 可能非常令人沮丧,并且只能用于有害/误导/truly_bad 答案,需要进行重大更改或应由其作者删除。答案之所以存在,是因为人们很慷慨并希望分享他们所知道的。一般来说,这些网站确实是在鼓励投票,以将有用的答案带到顶部。
【解决方案2】:

如果您使用的是 .NET 4.0,则可以将 string.ConcatEnumerable.Repeat 一起使用。

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

否则我会选择Adam's answer

我通常建议使用Andrey's answer 的原因仅仅是ToArray() 调用引入了多余的开销,而亚当建议的StringBuilder 方法可以避免这种开销。也就是说,至少它不需要 .NET 4.0 就可以工作;而且它既快速又简单(如果效率不是太在意的话,也不会杀死你)。

【讨论】:

  • 这可以很好地处理字符串——比如如果您需要连接不间断空格 ( )。但我认为如果你正在处理一个字符,字符串构造函数将是最快的......
  • 字符串构造函数只适用于一个字符。选择使用 Concat Repeat 将适用于字符串
  • 感谢您回答实际的标题问题!
  • 我喜欢这个答案!
  • 如果你得到 -System.Linq.Enumerable 等作为输出,那是因为你(好吧,这就是我)太快了,无法复制/粘贴和修改 sn-p。如果您需要将不同的字符串连接到 Enumerable.Repeat 的输出上,您需要这样做:Console.WriteLine(string.Concat("-", string.Concat(Enumerable.Repeat(indent, N))));
【解决方案3】:

最高效的字符串解决方案

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

【讨论】:

  • 当然是一个漂亮的单行。当然不是最高效的。 StringBuilder 在连接数量很少的情况下有一点开销。
  • 更高效的应该是:string result = new StringBuilder("---".Length * 5).Insert(0, "---", 5).ToString();跨度>
【解决方案4】:
public static class StringExtensions
{
    public static string Repeat(this string input, int count)
    {
        if (input.IsNullOrEmpty() || count <= 1)
            return input;

        var builder = new StringBuilder(input.Length * count);

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

        return builder.ToString();
    }
}

【讨论】:

  • 不妨将input.Length * count 传递给StringBuilder 构造函数,你不觉得吗?
  • Adam,我看到您在将输入添加到计数时遇到了测试 null 输入的麻烦,但随后允许它失败,依靠 Append 在给定 null 的情况下什么也不做。恕我直言,这不太明显:如果 null 是可能的输入,为什么不预先测试它并返回一个空字符串?
  • @AdamRobinson 是否返回一个空字符串来代替空值?我会用return input 替换return string.empty,这样你就可以得到空入/空出,空入/空出。
  • 需要检查count &gt; 0或者构造StringBuilder会抛出异常。
【解决方案5】:

对于许多情况,这可能是最巧妙的解决方案:

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

当时的用法是:

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

这建立在其他答案(尤其是@c0rd's)的基础上。除了简单之外,它还具有以下所有讨论的其他技术所不具备的特性:

  • 重复任意长度的字符串,而不仅仅是一个字符(按照 OP 的要求)。
  • 通过存储预分配有效使用StringBuilder

【讨论】:

  • 我同意,这太棒了。我刚刚将它添加到我的代码中,感谢 Bob!谢谢!
【解决方案6】:

如果您想要的字符串只包含一个字符,请使用String.PadLeft

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

欠款here

【讨论】:

  • 接吻。无论如何,我们需要什么 StringBuilders 和扩展?这是一个非常简单的问题。
  • 我不知道,这似乎用一些优雅的措辞解决了这个问题。顺便说一句,你叫谁'S'? :-)
  • 但这不就是the string constructor that takes a char and an int的一个不太明显的版本吗?
  • 用 String.Empty 代替 "" 会更好看...否则,很好的解决方案 ;)
  • @Steve BTW String.PadLeft 参数是相反的。 count 出现在填充字符之前。
【解决方案7】:

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

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

【讨论】:

    【解决方案8】:

    适用于字符串和字符:

    字符串和字符 [版本 1]

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

    字符串 [版本 2]:

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

    字符串和字符 [版本 3]

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

    仅限字符:

    '5' * 3; 
    //result: 555
    

    仅限字符:

    new string('5', 3);
    //result: 555
    

    扩展方式:

    (工作速度更快 - 更适合 WEB)

    public static class RepeatExtensions
    {
        public static string Repeat(this string str, int times)
        {
            var a = new StringBuilder();
            
            //Append is faster than Insert
            ( () => 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
    

    【讨论】:

    • 你的应该是公认的答案。这是 Html 中的一个很好的用法: var indents = string.Join("", Enumerable.Repeat(" ", Tabs * 3));
    • @JohnErnest for web 更好地使用我现在添加的扩展。我之所以写它是因为插入操作比附加操作相对较长
    • 我的用例是在浏览器窗口中为 SyntaxTree 编写一个简单的 Roslyn CSharpSyntaxWalker,除非我使用了 CSS 规则,否则选项卡或空格本身都不会缩进。
    • RepeatAction 似乎是一种不必要的晦涩方式来处理for
    • 有,也没有。使用它,您可以在其他地方执行 RepeatAction 而无需 for 语法。 :) 这在代码中也很有用。不仅在这个地方。
    【解决方案9】:

    我会选择 Dan Tao 的答案,但如果你不使用 .NET 4.0,你可以这样做:

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

    【讨论】:

    • 如果我能在我的项目中找到这个 sn-p,我会想知道谁违反了 KISS 以及为什么......否则很好
    • 你的new StringBuilder 至少应该传入str.Length*count
    【解决方案10】:
            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 之前这样做。
    【解决方案11】:

    重复打印一行。

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

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

    【讨论】:

    • 为什么不使用 Console.WriteLine 而不是在字符串末尾附加 \n ?
    【解决方案12】:

    对于一般用途,涉及 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() 避免了这种情况,同时仍然以极高的效率运行。

    此解决方案需要 O(1 + log N) 次迭代才能完成,该速率随重复次数成对数增加(重复次数加倍等于一次额外的迭代),比其他方法,按比例增加。

    【讨论】:

      【解决方案13】:

      我喜欢给出的答案。不过,我过去也使用过同样的方法:

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

      这将完成创建缩进,但从技术上讲,问题是重复一个字符串。如果字符串缩进类似于 >-

      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
      

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

      【讨论】:

        【解决方案14】:

        另一种方法是将string 视为IEnumerable&lt;char&gt;,并使用通用扩展方法将集合中的项目乘以指定的因子。

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

        所以在你的情况下:

        string indent = "---";
        var f = string.Concat(indent.Repeat(0)); //.NET 4 required
        //or
        var g = new string(indent.Repeat(5).ToArray());
        

        【讨论】:

          【解决方案15】:

          很惊讶没有人会走老路。我没有对这段代码提出任何任何声明,只是为了好玩:

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

          【讨论】:

          • 显然我把它留给精明的读者作为测试:) 非常精明,谢谢。
          • 命名参数@this 一点都不老派,这一直是个可怕的想法 :)
          • 我不喜欢使用关键字作为变量名,除非强制使用(例如使用 MVC 时 @class= "something",因为您需要引用 CSS 的类,但它是 C# 中的关键字(当然)。这不仅仅是我说的,它是一般的经验法则。虽然它肯定是可编译的代码并且是合法的,但考虑到易于阅读和打字,这两个都是实际的原因。我非常倾向于使用参数名称来描述正在发生的事情首先,Repeat(this string seed, int count) 可能更具说明性。
          • 很有趣,谢谢。我认为在这种情况下你可能是对的,@this 的描述性不如它可能的那样。但是总的来说,我认为扩展类或接口是很常见的,其中“this”的唯一合理名称是相当通用的。如果您有一个名为“instance”或“it”或“str”的参数(请参阅MSDN),那么您的意思可能是“this”。
          • 我基本上同意你的观点,但为了争论......因为我对我正在构建的字符串了解更多,所以我可以比 StringBuilder 做得更好。 StringBuilder 在分配内存时必须进行猜测。诚然,在许多情况下这不太重要,但有人可能会并行构建大量重复的字符串,并且很高兴能获得几个时钟周期 :)
          【解决方案16】:

          不确定这会如何执行,但它是一段简单的代码。 (我可能让它看起来比实际更复杂。)

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

          或者,如果您知道可以预期的最大级别数,则可以声明一个数组并对其进行索引。您可能希望将此数组设为静态或常量。

          string[] indents = new string[4] { "", indent, indent.Replace("-", "--"), indent.Replace("-", "---"), indent.Replace("-", "----") };
          output = indents[indentCount] + stringToBeIndented;      
          

          【讨论】:

            【解决方案17】:

            我没有足够的代表来评论亚当的回答,但 imo 最好的方法是这样的:

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

            你必须检查numTimes是否大于零,否则你会得到一个异常。

            【讨论】:

              【解决方案18】:

              添加我在整个项目中使用的扩展方法:

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

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

              【讨论】:

                【解决方案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))
                    }
                  }
                  

                  【讨论】:

                  • 查看我对凯尔回答的评论
                  • 如果使用 StringBuilder 而不是 String,这将是一个很好且快速的答案。但目前情况很糟糕。
                  猜你喜欢
                  • 2012-01-21
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-09-17
                  • 2010-12-05
                  • 2012-01-05
                  • 2010-10-05
                  相关资源
                  最近更新 更多