2009-02-10 11 views
117

Supongamos que tengo una cadena, por ejemplo,¿Puedo "multiplicar" una cadena (en C#)?

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

Quiero escribir básicamente varias veces, en función de un valor entero.

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

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

EDIT: sé que puedo escribir fácilmente mi propia función para implementar esto, me estaba preguntando si había algún operador de cadena raro que yo no sabía nada de

+3

puede simplemente usar un bucle –

+0

Posible duplicado de [¿Hay una forma fácil de devolver una cadena repetida X cantidad de veces?] (Http://stackoverflow.com/questions/3754582/is-there-an-easy -way-to-return-a-string-repeated-x-number-of-times) –

Respuesta

191

En .NET 4 se puede hacer esto:

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

Eso es bastante elegante. –

+8

Y no es mucho más en .NET 3.5: String.Concat (Enumerable.Repeat ("Hello", 4) .ToArray()) –

+2

No creo que sea elegante en absoluto.En Python, el código para hacer esto es: recorte * multiplicador (no es horrible ... pero tampoco es hermoso). –

59

Lamentablemente/afortunadamente, el la clase de cadena está sellada, por lo que no puede heredar de ella y sobrecargar el operador *. Puede crear un método de extensión embargo:

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

¡A dónde iba! Probablemente podrías optimizar utilizando el multiplicador source.Length * en el editor de StringBuilder –

+2

El comentario de Marc era justo donde * I * iba :) –

+1

Necesitas (multiplicador de fuente.Length *), no solo (multiplicador) –

9

que tendría que escribir un método - por supuesto, con C# 3.0 Podría ser un método de extensión:

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

a continuación:

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

Ni siquiera .NET3 tiene Enumerable.Repeat? –

+0

@Will - .NET 3 era WCF/WPF, etc., entonces no; sí existe en .NET 3.5, pero luego necesitarías '' string.Join' también, ¿por qué no simplemente hacer loop n veces? Mucho más directo. –

+0

Gracias - No estaba pensando correctamente acerca de 3.0 vs 3.5. En cuanto a por qué no solo usar un bucle, seguramente esa es la esencia del debate funcional versus imperativo. Publiqué una respuesta de .net 4 más abajo, lo que creo que no está mal en el debate 'inteligencia funcional' versus 'obviedad de bucle'. –

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, pero si por alguna razón desea hacer trampas con la funcionalidad incorporada, entonces puede ld hacer algo como esto:

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

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

O, si usted está utilizando .NET 4:

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

En lo personal no me molestaría sin embargo - un método de extensión personalizada es mucho más agradable.

+0

Nunca supe que había un truco como este. =) – Jronny

0

Bueno, aquí está mi opinión sobre el asunto:

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

estoy siendo un poco tonto, por supuesto, pero cuando tengo que tener la tabulación en las clases de la generación de código, Enumerable.Repeat lo hace por mí . Y sí, la versión de StringBuilder también está bien.

83

Tenga en cuenta que si su "cadena" es un solo carácter, hay una sobrecarga del constructor de cadena para manejarlo:

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

Esto fue realmente útil para mí. Gracias. – Kfirprods

10

Sólo por el bien de la exhaustividad - aquí es otra manera de hacer esto :

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

Creo que lo saqué de Stack Overflow hace un tiempo, así que no es mi idea.

0

Aquí está mi opinión sobre esto sólo para referencia futura:

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

Espero que realmente no uses 'ParallelEnumerable' en situaciones como esta. 'string.Join' necesita usar los elementos en orden, por lo que no se requiere paralelizar su generación. – Gabe

+0

@Gabe: Como los artículos son iguales y solo son copias de thisString, no hay necesidad de preocuparse por el orden aquí, supongo. – Jronny

+0

Estoy de acuerdo con muchos profesores en el campo que generalmente es bueno codificar para decir lo que quiere decir. No hay beneficio en decir que quieres este paralelismo y solo piensas secretamente "Bueno, sé que no será paralelo en este caso en particular" – sehe

2

Si tiene .Net 3.5, pero no 4.0, puede utilizar de System.Linq

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

Para obtener una sola cadena, aún necesitaría 'String.Concat', y en 3.5 también necesitaría' .ToArray() '. No es la solución más elegante, me temo. – Kobi

2

Puesto que cada uno está agregando sus propios ejemplos .NET4/LINQ, que bien podría añadir mi propia.(Básicamente, es DrJokepu, reducidos a una sola línea)

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 poco tarde (y sólo por diversión), si realmente desea utilizar el operador * para este trabajo, se puede hacer esto:

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

Y así:

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

Tenga en cuenta que, siempre y cuando usted es capaz de encontrar un comportamiento razonable para ellos, también puede manejar otros operadores a través de StringWrap clase, como \, ^, % etc ...

PS:

Multiply() créditos de extensión a @DrJokepu todos los derechos reservados ;-)

5

Esto es mucho más concisa:

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

El espacio de nombre using System.Text; se debe importar en este caso.

Cuestiones relacionadas