(C#で)文字列を「乗算」できますか?


136

たとえば、文字列があるとします。

string snip =  "</li></ul>";

整数値にもよりますが、基本的に複数回書きたいです。

string snip =  "</li></ul>";
int multiplier = 2;

// TODO: magic code to do this 
// snip * multiplier = "</li></ul></li></ul>";

編集:私はこれを実装するために自分の関数を簡単に書くことができることを知っています、私が知らなかった奇妙な文字列演算子があったのかと思っていました


回答:


222

.NET 4ではこれを行うことができます:

String.Concat(Enumerable.Repeat("Hello", 4))

9
そして、それは.NET 3.5ではそれほど多くありません:String.Concat(Enumerable.Repeat( "Hello"、4).ToArray())
Mark Foreman

4
エレガントではないと思います。Pythonでは、これを行うコードは次のとおりです:snip *マルチプライヤ(恐ろしいことではありません。
認知症のハリネズミ

7
@dementedhedgehogあなたはあなた自身の認知症を認めていることを知っていますが、あなたがそうであるように苦しんでさえ、Pythonの例がC#の質問に非常に良い答えをしなかったことを見ることができるかもしれません...私たちのほとんどは見ることができると思いますその言語選択は常に妥協であり、どんな質問に対するほとんどすべての答えは賛成か反対かの擁護で脚注される可能性があります。
ウィルディーン

1
@ウィル・ディーン:私はあなたがそこに持っているコードの優雅さについてのマシュー・ニコルズの声明に言及していました。私の知る限り、この問題については、現在のところ、C#用のコードはエレガントです。私がしようとしている点は次のとおりです:(私は信じています)C#を拡張して*演算子をオーバーロードしてint *文字列の乗算を許可することは非常に簡単です(Microsoftの場合)。これは実際には、現在存在するC#によって課せられた制約のコンテキスト内でエレガントなだけでなく、ある普遍的な意味でエレガントなものになります。
認知症のハリネズミ

@dementedhedgehog私にとって、それはバイナリがoperator*表すものに反します。一人一人に、私は推測します。
TEK 2017年

99

「文字列」が単一の文字のみの場合、それを処理する文字列コンストラクターのオーバーロードがあることに注意してください。

int multipler = 10;
string TenAs = new string ('A', multipler);

これは本当にプロです。
Zaven Zareyan

61

残念ながら/幸いにも、文字列クラスはシールされているので、それを継承して*演算子をオーバーロードすることはできません。ただし、拡張メソッドを作成できます。

public static string Multiply(this string source, int multiplier)
{
   StringBuilder sb = new StringBuilder(multiplier * source.Length);
   for (int i = 0; i < multiplier; i++)
   {
       sb.Append(source);
   }

   return sb.ToString();
}

string s = "</li></ul>".Multiply(10);

5
ちょうど私が行ったところ!あなた可能性*のStringBuilderのctorで乗数source.Lengthを使用して、おそらく最適化
マルクGravell

2
マークのコメントはが行くところだった:)
Jon Skeet

1
(乗数)だけでなく、(source.Length *乗数)が必要です
Marc Gravell

1
確定。シーンの背後に(その長さの)文字列を割り当て、それを変更します。これは、通常のリスト<T>などのように動作しません
マルクGravell

1
ここでは延長法が理想的です。
Chris Ballance、

12

私はこれでDrJokepuを使っていますが、何らかの理由で組み込み機能を使用してカンニングしたい場合は、次のようなことを行うことができます。

string snip = "</li></ul>";
int multiplier = 2;

string result = string.Join(snip, new string[multiplier + 1]);

または、.NET 4を使用している場合:

string result = string.Concat(Enumerable.Repeat(snip, multiplier));

個人的には私は気にしないだろう-カスタム拡張メソッドははるかに優れています。


1
このようなチートがあるとは知りませんでした。=)
Jronny、2010

10

完全を期すために、これを行う別の方法を次に示します。

public static string Repeat(this string s, int count)
{
    var _s = new System.Text.StringBuilder().Insert(0, s, count).ToString();
    return _s;
}

少し前にStack Overflowからそれを引き出したと思うので、私の考えではありません。


9

メソッドを記述する必要があります-もちろん、C#3.0では拡張メソッドになる可能性があります。

public static string Repeat(this string, int count) {
    /* StringBuilder etc */ }

次に:

string bar = "abc";
string foo = bar.Repeat(2);

.NET3にもEnumerable.Repeatがありませんでしたか?
ウィルディーン

@Will-.NET 3はWCF / WPFなどでした。.NET 3.5には存在しますが、それも必要にstring.Joinなります-なぜn回ループしないのですか?はるかに直接的。
Marc Gravell

ありがとう-私は3.0と3.5について適切に考えていませんでした。なぜループを使用しないのかについては、確かにそれが機能的な議論と命令的な議論の本質です。私は.net 4回答を下に投稿しました。これは、「機能的な賢さ」対「ループの自明性」の議論ではそれほど悪くないと思います。
Will Dean、

8

少し遅れて(そして面白さのために)、*この作業で本当に演算子を使用したい場合は、これを行うことができます:

public class StringWrap
{
    private string value;
    public StringWrap(string v)
    {
        this.value = v;
    }
    public static string operator *(StringWrap s, int n)
    {
        return s.value.Multiply(n); // DrJokepu extension
    }
}

など:

var newStr = new StringWrap("TO_REPEAT") * 5;

限り、あなたは彼らのために合理的な行動を見つけることができますように、あなたも介して他の演算子を扱うことができ、なおStringWrap、クラス、のような\^%等...

PS:

Multiply()@DrJokepuへの拡張クレジットは、すべての権利を留保します;-)


7

これははるかに簡潔です:

new StringBuilder().Insert(0, "</li></ul>", count).ToString()

using System.Text;この場合、名前空間をインポートする必要があります。


2
string Multiply(string input, int times)
{
     StringBuilder sb = new StringBuilder(input.length * times);
     for (int i = 0; i < times; i++)
     {
          sb.Append(input);
     }
     return sb.ToString();
}

2

.Net 3.5はあるが4.0はない場合は、System.Linqを使用できます。

String.Concat(Enumerable.Range(0, 4).Select(_ => "Hello").ToArray())

単一の文字列を取得するには、まだ必要です。3.5 String.Concatでは、も必要.ToArray()です。最もエレガントな解決策ではありません、私は恐れています。
コビ

2

誰もが独自の.NET4 / Linqサンプルを追加しているので、自分で追加することもできます。(基本的に、それはDrJokepuのものであり、ワンライナーに縮小されています)

public static string Multiply(this string source, int multiplier) 
{ 
    return Enumerable.Range(1,multiplier)
             .Aggregate(new StringBuilder(multiplier*source.Length), 
                   (sb, n)=>sb.Append(source))
             .ToString();
}

0

さて、これは私の問題です:

public static class ExtensionMethods {
  public static string Multiply(this string text, int count)
  {
    return new string(Enumerable.Repeat(text, count)
      .SelectMany(s => s.ToCharArray()).ToArray());
  }
}

もちろん私は少しばかげていますが、コード生成クラスで集計を行う必要がある場合は、Enumerable.Repeatがそれを行います。そして、そう、StringBuilderバージョンも問題ありません。


0

これは私の将来の参考のための私の見解です:

    /// <summary>
    /// Repeats a System.String instance by the number of times specified;
    /// Each copy of thisString is separated by a separator
    /// </summary>
    /// <param name="thisString">
    /// The current string to be repeated
    /// </param>
    /// <param name="separator">
    /// Separator in between copies of thisString
    /// </param>
    /// <param name="repeatTimes">
    /// The number of times thisString is repeated</param>
    /// <returns>
    /// A repeated copy of thisString by repeatTimes times 
    /// and separated by the separator
    /// </returns>
    public static string Repeat(this string thisString, string separator, int repeatTimes) {
        return string.Join(separator, ParallelEnumerable.Repeat(thisString, repeatTimes));
    }

ParallelEnumerableこのような状況では実際に使用しないでください。string.Join要素を順番に使用する必要があるため、生成を並列化する必要はありません。
Gabe

@Gabe:アイテムは同じで、実際にはthisStringの単なるコピーなので、ここでの順序を気にする必要はないと思います。
Jronny、2010

私は、あなたが何を意味するかを言うためにコード化することは通常良いことであるとフィールドの多くの教師に同意します。あなたは、このパラレルをしたいと言うだけで密かに「まあ、私はそれはとにかく、この特定のケースでは平行ではないだろう知っている」と考えるためにもメリットがありません
sehe

並列にすると速くなると思います、または教えてください。これがParallelEnumerableに変換する理由です。つまり、私が意味することを言うようにコードを書くと思います...ありがとう。
Jronny、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.