在C#中重复字符的最佳方法


812

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

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

Tabs(uint t)是一个函数,它返回一个string带有t的量\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; 
}

Answers:


1490

那这个呢:

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

哪里n是您要重复字符串的次数。

或更好:

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

2
有什么办法可以重复一遍吗?而不是使用“ \ t”如何使用“时间”
asdfkjasdfjk 13-4-3

6
@ user1478137或者更好(也可以更进一步):这个
Xynariz

161
string.Concat(Enumerable.Repeat("ab", 2));

退货

“阿巴布”

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

退货

“ aa”

从...

是否有内置函数在.net中重复字符串或char?


1
通过不使用Linq和with来使它变得更好StruingBuilder
Bitterblue 2014年

4
'' StringBuilder的'不一定快stackoverflow.com/questions/585860/...
Schiavini

6
它可能没有更快的速度,但是如果您预先指定正确的容量,它可以节省内存分配(压力),这与对其进行性能分析的微型基准测试一样重要。
wekempf '16

1
var strRepeat = string.Concat(Enumerable.Repeat(“ ABC”,1000000)); // 50ms
yongfa365 '12

1
string.Join在示例中,@ Pharap 更快,因为它们使用了空格分隔符。 string.Concat当没有定界符时,它是合适的。
卡特·梅德林

124

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

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

重覆角色new String('\t', count)是您的最佳选择。请参阅@CMS的答案


7
这是迄今为止String最快的性能。其他方法会产生过多的开销。
2015年

@midspace您是否知道有人解释了为什么其他答案更糟?我会假设原生String.Concat在内部进行的优化与StringBuilder一样
Marie

@Marie下面的文章解释了一些优点。support.microsoft.com/en-au/help/306822/…否则还有其他两个因素,StringBuilder允许使用字符串,并且不仅限于字符(尽管与原始问题无关),还包括字符串。上面的Concat答案必须首先使用Enumerable.Repeat创建一个数组。正如我所说,这是不必要的开销。
中部空间,

我以为它不会先创建数组,因为它可以逐项迭代。谢谢您的链接,我会阅读一下!
玛丽

63

最好的版本肯定是使用内置方式:

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

在其他解决方案中,首选最简单的解决方案。仅在证明速度太慢的情况下,才应寻求更有效的解决方案。

如果您使用a StringBuilder并事先知道其结果长度,然后还使用适当的构造函数,则效率会高得多,因为这意味着只会进行一次耗时的分配,而不会进行不必要的数据复制。 废话:当然,上面的代码更有效。


12
sb.Append('\ t',len);
dan-gph 2010年

7
我的基准测试显示new string('\t', len)比该StringBuilder方法快2到7倍。您为什么认为StringBuilder在这种情况下更有效?
StriplingWarrior

6
@StriplingWarrior感谢您纠正此问题(它已经在这里站了两年了,不少!)。
康拉德·鲁道夫

51

扩展方法:

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

39
曾几何时,人们使用while循环
prabhakaran 2013年

2
@prabhakaran我同意,但是Linq的优势是可以交流;使用命令式构造来重新实现Linq表达式几乎总是微不足道的。
Rodrick Chapman

10
Enumerable.Range(0, n).SelectMany(x => s)可以用简单的替换Enumerable.Repeat(s, n)
Palec 2016年

5
@Palec不,它不能。SelectMany每个单个虚拟对象的遗嘱都会x给出一个char值序列(因为string s实现IEnumerable<char>),并且所有这些char序列都被连接为一个长char序列。您建议的内容将改为IEnumerable<string>。不一样
Jeppe Stig

2
我错了,@ JeppeStigNielsen。感谢您的单挑。如果我真的想使用Enumerable.Repeat,则必须将这些字符串连接在一起:string.Concat(Enumerable.Repeat(s, n))。这已经发布过了
Palec

40

使用扩展方法呢?


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)) // char版本和
Debug.WriteLine(“-”。Repeat(1000000))//字符串版本


2
StringBuilder.Insert(Int32, String, Int32)正如Binoj Anthony回答的那样,可以通过使用来改善字符串版本的性能。
Palec 2016年

23

这个怎么样:

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

4
哈哈..这就是我一次陷入这种情况时所能想到的。但是我个人认为new string('\t', 10)这是最好的解决方案
shashwat 2013年


22

我知道这个问题已经有5年了,但是有一种简单的方法可以重复一个在.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(',');

退货

{“你好你好你好”, ””}

把事情简单化。



17

您的第一个示例使用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));
}

14

使用String.ConcatEnumerable.Repeat并且比使用便宜String.Join

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

9
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());

4

答案确实取决于您想要的复杂性。例如,我想用竖线勾勒出所有缩进,因此我的缩进字符串确定如下:

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

3

还有另一种方法

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

将结果字符串的长度传递给StringBuilder构造函数可节省重新分配。仍然,与使用string可以重复给定字符的构造函数相比,这种方法更加闲谈,效率更低,如已接受的答案中所示。
Palec

3

对我来说很好:

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

您可以创建扩展方法

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

那你可以这样用

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

1

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

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

有关此数组填充技术的更多信息,请参见用单个值填充数组的最快方法


0

尝试这个:

  1. 添加Microsoft.VisualBasic参考
  2. 使用:字符串结果= Microsoft.VisualBasic.Strings.StrDup(5,“ hi”);
  3. 请让我知道这对你有没有用。

在大多数情况下,当您需要这种功能时,添加对另一个程序集的依赖以及加载它的需求是不合理的。不过,很高兴知道.NET中有这样的事情。
Palec

有许多优点和在不同环境下利弊,所以每个人都应该根据不同的情况,她决定/他在不在。
托索Pankovski

-1

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

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

真正的标准.Net


它将仅添加填充,不再重复
-levi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.