C#で文字を繰り返す最良の方法


814

\tC#での文字列を生成する最良の方法は何ですか

私はC#を学び、同じことを言うさまざまな方法を実験しています。

Tabs(uint t)返す関数であるstringtの量\ts「は

たとえばTabs(3)返品"\t\t\t"

これらの3つの実装方法のうち、どれTabs(uint numTabs)が最適ですか?

もちろん、それは「最良」の意味によって異なります。

  1. LINQバージョンはたった2行です。しかし、RepeatとAggregateの呼び出しは、不必要に時間とリソースを消費していますか?

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

回答:


1491

これはどうですか:

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

どこにnあなたが文字列を繰り返したい回数です。

以上:

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

2
これを一言繰り返す方法はありますか?「\ t」を使用する代わりに、「時間」の使用方法
asdfkjasdfjk

6
@ user1478137または、より良い(下にも):これ
Xynariz

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

戻り値

「アバブ」

そして

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

戻り値

「ああ」

から...

.netで文字列または文字を繰り返す組み込み関数はありますか?


1
Linqを使わずにStruingBuilder
Bitterblue 2014

4
「」のStringBuilder「」は必ずしも速くないstackoverflow.com/questions/585860/...
Schiavini

6
速くはないかもしれませんが、正しい容量を事前に指定すると、メモリ割り当て(圧力)を節約できます。これは、これをプロファイリングするマイクロベンチマークと同じくらい重要です。
wekempf

1
var strRepeat = string.Concat(Enumerable.Repeat( "ABC"、1000000)); // 50ms
yongfa365 2018

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/…それ以外の2つの要因は、StringBuilderは文字列を許可し、char(元の質問には関係ありません)と文字列だけに制限されません。上記の連結回答では、最初にEnumerable.Repeatを使用して配列を作成する必要があります。言ったように、それは不必要なオーバーヘッドです。
ミッドスペース

最初は配列を作成しないと想定していました。これは、項目ごとに反復するだけだからです。リンクをありがとう、私はそれを読んでくれるでしょう!
マリー

63

最良のバージョンは確かに組み込みの方法を使用することです:

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

他の解決策のうち、最も簡単な方法を選択してください。これが遅すぎることが判明した場合にのみ、より効率的な解決策を模索してください。

aを使用しStringBuilder、その結果の長さが事前にわかっている場合は、適切なコンストラクタも使用すると、時間のかかる割り当てが1つだけ行われ、データの不必要なコピーが行われないため、これははるかに効率的です。 ナンセンス:もちろん、上記のコードはより効率的です。


12
sb.Append( '\ t'、len);
dan-gph

7
私のベンチマークはnew string('\t', len)StringBuilderアプローチよりも2倍から7倍速いことを示しています。StringBuilderこの場合、なぜ効率的だと思いますか?
StriplingWarrior 2011

6
@StriplingWarriorこれを修正していただきありがとうございます(2年間ここに立ってからですが、それ以上ではありません!)。
Konrad Rudolph、

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 '26 / 09/26

2
@prabhakaran同意するが、Linqの利点はコミュニケーションにある。命令構造を使用してLinq式を再実装することは、ほとんど常に簡単です。
Rodrick Chapman、

10
Enumerable.Range(0, n).SelectMany(x => s)シンプルなもので置き換えることができますEnumerable.Repeat(s, n)
Palec

5
@Palecいいえ、できません。SelectManyそれぞれのダミーの意志xは一連のchar値を提供し(string simplements 以降IEnumerable<char>)、それらのcharシーケンスはすべて1つの長いcharシーケンスに連結されます。あなたが提案するものは代わりにを与えますIEnumerable<string>。同じではありません。
Jeppe Stig Nielsen

2
私は間違っていました、@ JeppeStigNielsen。ヘッドアップをありがとう。本当に使用したい場合はEnumerable.Repeat、文字列を連結する必要がありますstring.Concat(Enumerable.Repeat(s, n))。これは以前にすでに投稿されています。
Palec 2017

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

文字列ではなく単純な文字に対して文字列ビルダーバージョンを使用するパフォーマンステストでは、パフォーマンスが大幅に低下することに注意してください。私のコンピューターでは、測定されたパフォーマンスの差は1:20です:Debug.WriteLine( '-'。Repeat(1000000)) // charバージョンと
Debug.WriteLine( "-"。Repeat(1000000))// stringバージョン


2
文字列バージョンのパフォーマンスは、Binoj Anthonyが答えたStringBuilder.Insert(Int32, String, Int32)ように、を使用することで改善される可能性があります。
Palec

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年

このトリックはEssential C#6.0でも使用されます。
マネー指向のプログラマー

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

戻り値

{"ハローハローハロー"、 ""}

複雑にしないでおく。


19

'\ t'をn回繰り返したいとしましょう。

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

1
ありがとう。これも非常に高速です。codereview.stackexchange.com/questions/36391/...
Sunsetquest

私はいつもこのようにしてきました。拡張メソッドにラップされていても、ここに掲載されている他の実装よりも簡単です。OPは文字列ではなく\ tを繰り返したいだけであったことに注意してください。
マイケルリボン2016

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.Concat、使用するEnumerable.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、2018年

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 2017

そこに多くの長所と短所異なる文脈では、誰もが彼女/彼がしている状況に応じて決める必要がありますので。
トーソーPankovski

-1

以前の提案と非常に似ていますが、私はそれを単純に保ち、以下を適用するのが好きです:

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

本当に標準的な.Net、


パディングを追加するだけで、繰り返さない
levi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.