2009-02-10 8 views
117

Supponiamo che io sono una stringa, ad esempio,Posso "moltiplicare" una stringa (in C#)?

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

voglio scrivere in fondo è più volte, a seconda di un certo valore intero.

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

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

EDIT: So che posso facilmente scrivere il mio funzione per implementare questo, mi stavo chiedendo se ci fosse qualche strano operatore stringa che io non conoscevo

+3

si potrebbe semplicemente utilizzare un ciclo –

+0

Possibile duplicato di [C'è un modo semplice per restituire una stringa ripetuta X volte il numero?] (Http://stackoverflow.com/questions/3754582/is-there-an-easy -way-to-return-a-string-repeat-x-number-of-times) –

risposta

191

In .NET 4 si può fare questo:

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

È piuttosto elegante. –

+8

E non è molto di più in .NET 3.5: String.Concat (Enumerable.Repeat ("Hello", 4) .ToArray()) –

+2

Non penso che sia elegante.In Python il codice per farlo è: snip * moltiplicatore (non è orribile .. ma nemmeno è bello). –

59

Purtroppo/per fortuna, il la classe string è sigillata, quindi non puoi ereditarla e sovraccaricare l'operatore *. È possibile creare un metodo di estensione però:

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

Proprio dove stavo andando! Probabilmente potresti ottimizzare usando il moltiplicatore source.Length * nel codificatore StringBuilder –

+2

Il commento di Marc era proprio dove * I * stava andando :) –

+1

Hai bisogno (source.Length * moltiplicatore), non solo (moltiplicatore) –

9

che avrebbe dovuto scrivere un metodo - naturalmente, con C# 3.0 potrebbe essere un metodo di estensione:

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

poi:

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

Non ha nemmeno .NET3 avere Enumerable.Repeat? –

+0

@Will - .NET 3 era WCF/WPF ecc, quindi no; esiste in .NET 3.5, ma poi dovresti anche eseguire 'string.Join' - perché non solo ciclo n volte? Molto più diretto –

+0

Grazie - Non stavo pensando correttamente a 3.0 vs 3.5. Per quanto riguarda il motivo per cui non basta usare un ciclo, sicuramente questa è l'essenza del dibattito funzionale vs imperativo? Ho postato una risposta .net 4 più in basso, che ritengo non sia poi così male nel dibattito sulla "intelligenza funzionale" e "loop ovvio". –

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

I'm with DrJokepu on this one, ma se per qualche motivo si desiderava imbrogliare utilizzando la funzionalità integrata, quindi si ld fare qualcosa di simile:

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

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

Oppure, se si sta utilizzando .NET 4:

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

Personalmente non mi preoccuperei se - un metodo di estensione personalizzata è molto più bello.

+0

Non ho mai saputo che ci fosse un imbroglione come questo. =) – Jronny

0

Okay, ecco il mio prendere sulla questione:

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

devo essere un po 'sciocco, naturalmente, ma quando ho bisogno di avere tabulazione nelle classi di codici che generano, Enumerable.Repeat lo fa per me . E sì, anche la versione StringBuilder va bene.

83

Nota che se il "stringa" è solo un singolo carattere, v'è un sovraccarico del costruttore stringa per gestirlo:

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

Questo è stato davvero utile per me. Grazie. – Kfirprods

10

Solo per amor di completezza - qui è un altro modo di fare questo :

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

penso ho tirato quella di Stack Overflow qualche tempo fa, quindi non è la mia idea.

0

Ecco il mio prendere su questo solo per riferimento futuro:

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

Spero che tu non usi veramente ParallelEnumerable in situazioni come questa. 'string.Join' deve utilizzare gli elementi in ordine, quindi la parallelizzazione della loro generazione non è richiesta. – Gabe

+0

@Gabe: Dato che gli articoli sono gli stessi e sono in realtà solo copie di thisString, non c'è motivo di preoccuparsi per l'ordine qui, immagino. – Jronny

+0

Sono d'accordo con molti insegnanti sul campo che di solito è opportuno codificare per dire cosa intendi. Non c'è nessun vantaggio nel dire che vuoi questo parallelo e solo segretamente pensi "Beh, so che non sarà parallelo in questo caso particolare comunque" – sehe

2

Se si dispone di .Net 3.5, ma non 4.0, è possibile utilizzare System.Linq's

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

Per ottenere una singola stringa avresti ancora bisogno di 'String.Concat', e su 3.5 avresti anche bisogno di' .ToArray() '. Non è la soluzione più elegante, temo. – Kobi

2

Poiché tutti aggiungono i propri esempi .NET4/Linq, potrei aggiungere il mio.(In sostanza, DrJokepu di, ridotti ad una battuta)

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

Un po 'in ritardo (e solo per divertimento), se davvero si vuole utilizzare l'operatore * per questo lavoro, si può fare questo:

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

E così:

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

si noti che, finché si è in grado di trovare un comportamento ragionevole per loro, è possibile gestire anche altri operatori attraverso StringWrap di classe, come \, ^, % ecc ...

PS:

Multiply() crediti estensione a @DrJokepu tutti i diritti riservati ;-)

5

Questo è molto più conciso:

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

Il namespace using System.Text; dovrebbe essere importato in questo caso.