【问题标题】:Best way to repeat a character in C#在 C# 中重复字符的最佳方法
【发布时间】:2010-09-29 12:45:43
【问题描述】:

在 C# 中生成 \t 字符串的最佳方法是什么

我正在学习 C# 并尝试用不同的方式来表达同一件事。

Tabs(uint t) 是一个函数,它返回 stringt 数量的 \t

例如Tabs(3) 返回"\t\t\t"

这三种实现Tabs(uint numTabs)的方法中哪一种最好?

当然,这取决于“最佳”的含义。

  1. LINQ 版本只有两行,很好。但是对重复和聚合的调用是否会不必要地消耗时间/资源?

  2. StringBuilder 版本非常清晰,但 StringBuilder 类是否会慢一些?

  3. string 版本是基本的,这意味着它很容易理解。

  4. 这根本不重要吗?他们都是平等的吗?

这些都是帮助我更好地了解 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; 
}

【问题讨论】:

    标签: c# .net string


    【解决方案1】:

    这个呢:

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

    其中n 是您要重复该字符串的次数。

    或者更好:

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

    【讨论】:

    • 有没有办法重复这个单词?而不是使用'\t'如何使用“时间”
    • @user1478137 或者,更好(也更进一步):this
    • 当用空格替换 '\t' 时(即“”),我发现在某些笔记本电脑上它被视为一个空格,而在其他一些笔记本电脑上,在后面添加了一个“返回键”行尾的空格。下面建议的另一个答案使用 string.Concat,在某些笔记本电脑上也以同样奇怪的方式表现。知道为什么会这样吗?谢谢
    【解决方案2】:
    string.Concat(Enumerable.Repeat("ab", 2));
    

    返回

    “阿巴”

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

    返回

    “啊”

    来自...

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

    【讨论】:

    • 在没有 Linq 和 StruingBuilder 的情况下做得更好!
    • ''StringBuilder'' 不一定更快stackoverflow.com/questions/585860/…
    • 它可能不会更快,但如果您预先指定正确的容量,它可以节省内存分配(压力),这与分析它的微观基准一样重要。
    • var strRepeat = string.Concat(Enumerable.Repeat("ABC", 1000000)); //50毫秒
    【解决方案3】:

    在所有版本的 .NET 中,您都可以这样重复一个字符串:

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

    要重复一个字符,new String('\t', count) 是您最好的选择。见the answer by @CMS

    【讨论】:

    • 这是迄今为止最快的 String 性能。其他方法会产生过多的开销。
    • @midspace 你知道是否有人解释了为什么其他答案更糟?我会假设本机 String.Concat 将与 StringBuilder 一样在内部进行优化
    • @Marie 下面的文章解释了一些优点。 @ 987654322@ 否则还有两个因素,StringBuilder 允许字符串并且不仅限于一个字符(尽管这与原始问题无关),并且上面的 string.Concat 答案必须首先使用 Enumerable 创建一个数组。重复。正如我所说,这是不必要的开销。
    • 我以为它不会首先创建一个数组,因为它只能逐项迭代。谢谢你的链接,我会读一读!
    【解决方案4】:

    最好的版本当然是使用内置的方式:

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

    在其他解决方案中,选择最简单的;仅当这被证明太慢时,才努力寻求更有效的解决方案。

    如果你使用StringBuilder并提前知道它的结果长度,那么也使用适当的构造函数,这样效率更高,因为这意味着只发生一次耗时的分配,并且没有不必要的复制数据。 废话:当然上面的代码效率更高。

    【讨论】:

    • 我的基准测试显示 new string('\t', len)StringBuilder 方法快 2 到 7 倍。为什么你认为StringBuilder 在这种情况下效率更高?
    • @StriplingWarrior 感谢您的纠正(在它已经站在这里两年之后,不少于!)。
    【解决方案5】:

    扩展方法:

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

    【讨论】:

    • Enumerable.Range(0, n).SelectMany(x =&gt; s) 可以替换为简单的Enumerable.Repeat(s, n)
    • @Palec 不,它不能。 SelectMany 将为每个单独的虚拟x 提供一系列char 值(因为string s 实现IEnumerable&lt;char&gt;),并且所有这些char 序列连接到一个长char 序列。您的建议将改为提供IEnumerable&lt;string&gt;。不一样。
    • 我错了,@JeppeStigNielsen。感谢您的提醒。如果我真的想使用Enumerable.Repeat,我必须将字符串连接在一起:string.Concat(Enumerable.Repeat(s, n))。这已经是posted before
    【解决方案6】:

    使用扩展方法呢?


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

    然后你可以写:

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

    请注意,对简单字符而不是字符串使用 stringbuilder 版本的性能测试会给您带来主要的性能损失: 在我的电脑上,测量性能的差异是 1:20: Debug.WriteLine('-'.Repeat(1000000)) //字符版本和
    Debug.WriteLine("-".Repeat(1000000)) //字符串版本

    【讨论】:

    【解决方案7】:

    这个怎么样:

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

    【讨论】:

    • 哈哈..这就是我曾经陷入这种情况时所能想到的。但我个人发现new string('\t', 10) 是最好的解决方案
    【解决方案8】:

    我知道这个问题已经有五年的历史了,但是有一种简单的方法可以重复一个甚至在 .Net 2.0 中有效的字符串。

    重复一个字符串:

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

    返回

    “你好,你好,你好,”

    将字符串作为数组重复:

    // 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(',');
    

    返回

    {“你好”、“你好”、“你好”、“”}

    保持简单。

    【讨论】:

      【解决方案9】:

      假设你想重复 '\t' n 次,你可以使用;

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

      【讨论】:

      • 我一直都是这样做的。即使包装在扩展方法中,它也比此处发布的其他实现更简单。请注意,OP 只是想重复 \t,而不是字符串。
      【解决方案10】:

      您使用Enumerable.Repeat 的第一个示例:

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

      可以用String.Concat更简洁地重写:

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

      【讨论】:

        【解决方案11】:

        使用String.ConcatEnumerable.Repeat 会更便宜 比使用String.Join

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

        【讨论】:

          【解决方案12】:
          var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());
          

          【讨论】:

            【解决方案13】:

            答案实际上取决于您想要的复杂性。比如我想用竖线勾勒出我所有的缩进,所以我的缩进字符串是这样确定的:

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

            【讨论】:

              【解决方案14】:

              还有一种方法

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

              【讨论】:

              • 将生成的字符串长度传递给StringBuilder 构造函数可以节省重新分配。尽管如此,这比使用可以重复给定字符的 string 构造函数更健谈且效率更低,如已接受的答案中所示。
              【解决方案15】:

              对我来说很好:

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

              【讨论】:

                【解决方案16】:

                你可以创建一个扩展方法

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

                那你就可以这样使用了

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

                【讨论】:

                  【解决方案17】:

                  毫无疑问,公认的答案是重复单个字符的最佳和最快方式。

                  Binoj Anthony 的回答是一种简单且非常有效的重复字符串的方法。

                  但是,如果您不介意更多代码,您可以使用我的数组填充技术更快地高效地创建这些字符串。在我的比较测试中,以下代码的执行时间大约是 StringBuilder.Insert 代码的 35%。

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

                  有关此数组填充技术的更多信息,请参阅Fastest way to fill an array with a single value

                  【讨论】:

                    【解决方案18】:

                    试试这个:

                    1. 添加 Microsoft.VisualBasic 参考
                    2. 使用:字符串结果 = Microsoft.VisualBasic.Strings.StrDup(5,"hi");
                    3. 让我知道它是否适合您。

                    【讨论】:

                    • 添加对另一个程序集的依赖并需要加载它在大多数情况下当您需要此类功能时是不合理的。不过,很高兴知道 .NET 中有这样的东西。
                    • 在不同的情况下有很多利弊,所以每个人都应该根据自己所处的情况来决定。
                    【解决方案19】:

                    用 6,435 个 z 填充屏幕 $str = [System.Linq.Enumerable]::Repeat([string]::new("z", 143), 45)

                    $str

                    【讨论】:

                      【解决方案20】:

                      尽管与之前的建议非常相似,但我喜欢保持简单并应用以下内容:

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

                      真正的标准.Net,

                      【讨论】:

                      • 它只会添加填充,不会重复
                      • @levi:填充有什么问题? string result = string.Empty.PadRight('\t',5) 是否没有返回所需的结果(在本例中为 5 个选项卡)?
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-10-12
                      • 2013-09-18
                      • 1970-01-01
                      • 2016-11-17
                      相关资源
                      最近更新 更多