Bir dizeyi “çarpabilir miyim” (C # ile)?


136

Diyelim ki bir dizem var, örneğin,

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

Temelde bazı tamsayı değerine bağlı olarak, birden çok kez yazmak istiyorum.

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

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

EDIT: Bunu uygulamak için kendi işlevimi kolayca yazabilirim biliyorum, sadece bilmediğim bazı garip dize operatörü olup olmadığını merak ediyordum


Yanıtlar:


222

.NET 4'te şunları yapabilirsiniz:

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

9
Ve .NET 3.5'te daha fazla değil: String.Concat (Enumerable.Repeat ("Hello", 4) .ToArray ())
Mark Foreman

4
Hiç zarif olduğunu sanmıyorum. Python bunu yapmak için kod: snip * çarpanı (Bu korkunç değil .. ama ne de güzel).
demanslı kirpi

7
@ dementedhedgehog Kendi demansınızı kabul ettiğinizi biliyorum, ama sizin yaptığınız gibi acı çekiyor olsanız bile, bir Python örneğinin C # sorusuna çok iyi bir cevap veremeyeceğini görebilirsiniz ... dil seçimi her zaman bir uzlaşmadır ve herhangi bir soruya verilecek herhangi bir cevap, ya da karşı ya da savunuculukla dipnotlanabilir.
Dean

1
@will dean: Matthew Nichols'ın söz konusu kodun zarafeti hakkındaki ifadesinden bahsediyorum. Kodunuzu söyleyebildiğim kadarıyla şu anda olduğu gibi C # için bu sorun için zarif. Yapmaya çalıştığım nokta: (sanırım) int * string çarpımına izin vermek için * operatörünü aşırı yüklemek için C # 'ı uzatmak çok kolay olurdu (microsoft için). O zaman aslında bazı evrensel anlamda zarif olurdu, imho, sadece şu anda var olduğu gibi C # tarafından dayatılan kısıtlamalar bağlamında zarif değil.
demanslı kirpi

@ dementedhedgehog Bana göre, bu ikili ikiliyi operator*temsil eder. Her biri için, sanırım.
TEK

99

Eğer "dizginiz" sadece tek bir karakter ise, dizge yapıcısının onu işleyebileceği bir aşırı yüklenme olduğunu unutmayın:

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

Bu gerçekten profesyonel.
Zaven Zareyan

61

Ne yazık ki / neyse ki, dize sınıfı mühürlenmiştir, bu nedenle ondan devralmaz ve * işlecini aşırı yükleyemezsiniz. Yine de bir uzantı yöntemi oluşturabilirsiniz:

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
Tam nereye gittiğimi! StringBuilder ctor'da source.Length * çarpanını kullanarak optimize edebilirsiniz
Marc Gravell

2
Marc'ın yorumu tam gittiğim yerdi :)
Jon Skeet

1
İhtiyacınız olan (source.Length * çarpanı), sadece (çarpan) değil
Marc Gravell

1
Çok emin. Sahnelerin arkasına bir dize (bu uzunlukta) ayırır, sonra onu değiştirir. Normal bir Liste <T>
vb.Gibi

1
Genişletme yöntemi burada idealdir.
Chris Ballance

12

Bu konuda DrJokepu ile beraberim , ancak herhangi bir nedenle yerleşik işlevselliği kullanarak hile şey yapabilirsiniz:

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

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

Veya .NET 4 kullanıyorsanız:

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

Şahsen olsa rahatsız olmaz - özel bir uzantı yöntemi çok daha hoş.


1
Böyle bir hile olduğunu hiç bilmiyordum. =)
Jronny

10

Sadece bütünlük uğruna - işte bunu yapmanın başka bir yolu:

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

Sanırım bunu bir süre önce Stack Overflow'dan aldım, bu benim fikrim değil.


9

Bir yöntem yazmanız gerekir - elbette, C # 3.0 ile bir uzantı yöntemi olabilir:

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

sonra:

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

.NET3 bile Numaralandırılabilir değil mi?
Dean Dean

@Will - .NET 3, WCF / WPF vb. .NET 3.5'te var, ancak sonra da string.Joinbuna ihtiyacınız olacak - neden sadece n kez döngü yapmıyorsunuz? Çok daha doğrudan.
Marc Gravell

Teşekkürler - 3.0 vs 3.5 hakkında düzgün düşünmüyordum. Neden sadece bir döngü kullanmamaya gelince, şüphesiz bu işlevsel ve zorunlu tartışmanın özüdür? Ben 'işlevsel zekâ' vs 'döngüsel açıklık' tartışmasında çok kötü olmadığını düşünüyorum aşağı bir .net 4 cevap yayınladı.
Dean Dean

8

Biraz geç (ve sadece eğlence için), *operatörü bu iş için gerçekten kullanmak istiyorsanız , bunu yapabilirsiniz:

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

Ve bu yüzden:

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

Ayrıca aracılığıyla diğer operatörleri işleyebilir, sürece onlar için makul bir davranış bulmak mümkün olduğu gibi, unutmayın StringWrapsınıfın gibi \, ^,% vs ...

Not:

Multiply()@DrJokepu'ya uzantı kredisi tüm hakları saklıdır ;-)


7

Bu çok daha özlü:

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

using System.Text;Bu durumda ad alanı içe aktarılmalıdır.


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'iniz varsa ancak 4.0'ınız yoksa, System.Linq'leri kullanabilirsiniz.

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

Tek bir dize almak için hala ihtiyacınız olacak String.Concatve 3.5'te de ihtiyacınız olacak .ToArray(). Korkarım en zarif çözüm değil.
Kobi

2

Herkes kendi .NET4 / Linq örneklerini eklediğinden, kendi .NET4 / Linq örneklerini de ekleyebilirim. (Temel olarak, DrJokepu'nun, bir astara indirgenmiş)

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

Tamam, işte konuyu ele alacağım:

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

Tabii biraz aptallık yapıyorum, ama kod üreten sınıflarda tablolama gerektiğinde, Enumerable.Repeat bunu benim için yapıyor. Ve evet, StringBuilder sürümü de gayet iyi.


0

İşte sadece ileride başvurmak için bunu benim almak:

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

Umarım böyle durumlarda gerçekten kullanmazsınız ParallelEnumerable. string.Joinelemanları sırayla kullanması gerekir, bu yüzden onların neslinin paralelleştirilmesi çağrılmaz.
Gabe

@Gabe: Öğeler aynı ve gerçekten bunun kopyaları olduğundan, burada sipariş verme konusunda endişelenmenize gerek yok sanırım.
Jronny

Alandaki birçok öğretmenle, ne demek istediğinizi söylemenin genellikle iyi olduğunu kabul ediyorum. Bunun paralel olmasını istediğinizi söylemenin bir yararı yok ve sadece gizlice "Bu özel durumda yine de paralel olmayacağını biliyorum"
Mart'ta

Bence paralel yapmak onu hızlandırıyor, ya da lütfen beni aydınlatın. Bu yüzden bu ParallelEnumerable dönüştürüyorum, bu yüzden ne demek istediğimi söylemek için kod düşünüyorum ... Teşekkürler.
11:10
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.