2010-09-20 12 views
212

Estoy tratando de insertar un cierto número de sangrías antes de una cadena en función de la profundidad de un ítem y me pregunto si hay una forma de devolver una cadena repetida X veces. Ejemplo:¿Hay alguna manera fácil de devolver una cadena repetida X veces?

string indent = "---"; 
Console.WriteLine(indent.Repeat(0)); //would print nothing. 
Console.WriteLine(indent.Repeat(1)); //would print "---". 
Console.WriteLine(indent.Repeat(2)); //would print "------". 
Console.WriteLine(indent.Repeat(3)); //would print "---------". 
+7

No estoy seguro si esto es aplicable, pero es posible que desee ver en la [IndentedTextWriter] (http://msdn.microsoft.com/en-us/library/system.codedom.compiler.indentedtextwriter%28v=VS.100%29.aspx) también. –

+0

¿Desea considerar cambiar la respuesta aceptada ya que su pregunta es sobre la repetición de cadenas y no de caracteres que representa la respuesta aceptada? Desde hoy hasta .Net v4.7, cualquier constructor sobrecargado de la clase 'String' no está tomando una cadena como parámetro para crear repeticiones que podrían haber hecho que la respuesta aceptada se ajuste perfectamente. – RBT

Respuesta

380

Si sólo se van a repetir el mismo carácter que se pueda utilizar el string constructor que acepta un char y el número de veces que se repita new String(char c, int count).

Por ejemplo, para repetir un guión cinco veces:

string result = new String('-', 5); // ----- 
+5

Gracias por recordarme esta pequeña característica. Creo que se perdió en un rincón de mi mente. –

+4

Impresionante, no tenía idea. –

+1

las clases en el framework nunca dejan de sorprender ... ya hemos hecho mucho por nosotros ... – desigeek

17

Uso String.PadLeft, si su cadena deseada contiene un solo carbón.

public static string Indent(int count, char pad) 
{ 
    return String.Empty.PadLeft(count, pad); 
} 

crédito debido here

+1

BESO. ¿Para qué necesitamos StringBuilders y extensiones, de todos modos? Este es un problema muy simple. – DOK

+0

No sé, esto parece resolver el problema tal como se expresa con cierta elegancia. Y, por cierto, ¿a quién llamas 'S'? :-) –

+6

Pero, ¿no es esta una versión menos obvia de [el constructor 'string' que toma' char' y 'int'] (http://msdn.microsoft.com/en-us/library /xsa4321w.aspx)? –

36
public static class StringExtensions 
{ 
    public static string Repeat(this string input, int count) 
    { 
     if (!string.IsNullOrEmpty(input)) 
     { 
      StringBuilder builder = new StringBuilder(input.Length * count); 

      for(int i = 0; i < count; i++) builder.Append(input); 

      return builder.ToString(); 
     } 

     return string.Empty; 
    } 
} 
+6

También podría pasar 'input.Length * count' al constructor' StringBuilder', ¿no crees? –

+0

@Dan: Parece una buena idea, ¿no? –

+0

Y si pasa 'input.Length * count' al constructor' StringBuilder', podría omitir 'StringBuilder' y crear un char [] del tamaño correcto de inmediato. – dtb

182

Si está utilizando .NET 4.0, se puede utilizar junto con string.ConcatEnumerable.Repeat.

int N = 5; // or whatever 
Console.WriteLine(string.Concat(Enumerable.Repeat(indent, N))); 

De lo contrario, me gustaría ir con algo así como Adam's answer.

La razón por la que generalmente no lo aconsejan utilizar Andrey's answer es simplemente que la llamada ToArray() supone cargas superfluas que se evita con el enfoque sugerido por Adam StringBuilder. Dicho esto, al menos funciona sin requerir .NET 4.0; y es rápido y fácil (y no te va a matar si la eficiencia no es una gran preocupación).

+2

Esto funcionará muy bien con cadenas, como si necesita concaturar espacios sin interrupción ( ). Pero supongo que el constructor de cadenas será más rápido si se trata de un char ... – woodbase

+0

El constructor de cadenas solo funcionará para un char. la opción de usar Concat Repeat funcionará para las cadenas –

+0

¡Gracias por responder la pregunta del título real! –

-2

¡Puedes crear un ExtensionMethod para hacer eso! solución

public static class StringExtension 
{ 
    public static string Repeat(this string str, int count) 
    { 
    string ret = ""; 

    for (var x = 0; x < count; x++) 
    { 
     ret += str; 
    } 

    return ret; 
    } 
} 

O usando @ Dan Tao:

public static class StringExtension 
{ 
    public static string Repeat(this string str, int count) 
    { 
    if (count == 0) 
     return ""; 

    return string.Concat(Enumerable.Repeat(indent, N)) 
    } 
} 
+3

Ver mi comentario a la respuesta de Kyle –

2
 string indent = "---"; 
     string n = string.Concat(Enumerable.Repeat(indent, 1).ToArray()); 
     string n = string.Concat(Enumerable.Repeat(indent, 2).ToArray()); 
     string n = string.Concat(Enumerable.Repeat(indent, 3).ToArray()); 
+1

@ Adam: Supongo que tendrías que hacer ese pre.NET 4.0. –

11

Yo iría por la respuesta de Dan Tao, pero si usted no está utilizando .NET 4.0 que puedo hacer algo por el estilo:

public static string Repeat(this string str, int count) 
{ 
    return Enumerable.Repeat(str, count) 
        .Aggregate(
         new StringBuilder(), 
         (sb, s) => sb.Append(s)) 
        .ToString(); 
} 
+2

Ese es un hermoso recorte de código. – miltonb

+2

Si encuentro este fragmento en mi proyecto, me pregunto quién ha estado violando el KISS y por qué ... bueno de lo contrario – Noctis

0

Otro enfoque es considerar string como IEnumerable<char> y tener un método de extensión genérico que multiplicará los elementos en una colección por el factor especificado.

public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int times) 
{ 
    source = source.ToArray(); 
    return Enumerable.Range(0, times).SelectMany(_ => source); 
} 

Así, en su caso:

string indent = "---"; 
var f = string.Concat(indent.Repeat(0)); //.NET 4 required 
//or 
var g = new string(indent.Repeat(5).ToArray()); 
1

sorprende que nadie se fue la vieja escuela. No estoy haciendo ningún afirmaciones acerca de este código, pero sólo por diversión:

public static string Repeat(this string @this, int count) 
{ 
    var dest = new char[@this.Length * count]; 
    for (int i = 0; i < dest.Length; i += 1) 
    { 
     dest[i] = @this[i % @this.Length]; 
    } 
    return new string(dest); 
} 
+0

* Obviamente * Lo dejé como prueba para el lector astuto :) Muy astuto, gracias. – OlduwanSteve

+1

No hay nada antiguo en nombrar un parámetro @this, eso siempre ha sido una idea horrible :) –

+0

¿Incluso en el contexto de un método de extensión? Parece razonable cuando @esto es de hecho ... 'esto', pero siempre estoy dispuesto a ser influido. ¿Es eso un juicio estético o hay un inconveniente práctico? – OlduwanSteve

1

No estoy seguro de cómo esto podría llevar a cabo, pero es una pieza fácil de código. (Probablemente he hecho que parezca más complicado de lo que es.)

int indentCount = 3; 
string indent = "---"; 
string stringToBeIndented = "Blah"; 
// Need dummy char NOT in stringToBeIndented - vertical tab, anyone? 
char dummy = '\v'; 
stringToBeIndented.PadLeft(stringToBeIndented.Length + indentCount, dummy).Replace(dummy.ToString(), indent); 

Alternativamente, si se conoce el número máximo de niveles que puede esperar, sólo podría declarar una matriz y el índice en ella. Probablemente quieras hacer esta matriz estática o una constante.

string[] indents = new string[4] { "", indent, indent.Replace("-", "--"), indent.Replace("-", "---"), indent.Replace("-", "----") }; 
output = indents[indentCount] + stringToBeIndented;  
1

no tengo representante suficiente para comentar sobre la respuesta de Adán, pero la mejor manera de hacerlo OMI es la siguiente:

public static string RepeatString(string content, int numTimes) { 
     if(!string.IsNullOrEmpty(content) && numTimes > 0) { 
      StringBuilder builder = new StringBuilder(content.Length * numTimes); 

      for(int i = 0; i < numTimes; i++) builder.Append(content); 

      return builder.ToString(); 
     } 

     return string.Empty; 
    } 

Usted debe comprobar para ver si numTimes es mayor que cero De lo contrario, recibirá una excepción.

19

solución mas potente para la cadena

string result = new StringBuilder().Insert(0, "---", 5).ToString(); 
+0

Ese es un buen punto, una gran respuesta. –

+0

Me super likey ... – nashwan

2

me gusta la respuesta dada. A lo largo de las líneas sames aunque es lo que he usado en el pasado:

"" .PadLeft (3 * sangría, '-')

Esta cumplirá la creación de un guión, pero técnicamente la cuestión era repetir una cuerda. Si la sangría de cadena es algo así como> - <, entonces esto y la respuesta aceptada no funcionarían. En este caso, la solución de c0rd que usa stringbuilder se ve bien, aunque la sobrecarga de stringbuilder puede no ser la más eficaz. Una opción es construir una matriz de cadenas, rellenarlo con sangrías y luego concat. A la Pena:

int Indent = 2; 

string[] sarray = new string[6]; //assuming max of 6 levels of indent, 0 based 

for (int iter = 0; iter < 6; iter++) 
{ 
    //using c0rd's stringbuilder concept, insert ABC as the indent characters to demonstrate any string can be used 
    sarray[iter] = new StringBuilder().Insert(0, "ABC", iter).ToString(); 
} 

Console.WriteLine(sarray[Indent] +"blah"); //now pretend to output some indented line 

A todos nos encanta una solución inteligente, pero a veces lo mejor es lo mejor.

0

No vi esta solución. Me resulta más sencillo para los que actualmente estoy en el desarrollo de software:

public static void PrintFigure(int shapeSize) 
{ 
    string figure = "\\/"; 
    for (int loopTwo = 1; loopTwo <= shapeSize - 1; loopTwo++) 
    { 
     Console.Write($"{figure}"); 
    } 
} 
2

Esto se basa en otras respuestas (particularmente @ c0rd de).

Para muchos escenarios, esta es probablemente la solución más elegante:

public static class StringExtensions 
{ 
    public static string Repeat(this string s, int n) 
     => new StringBuilder(s.Length * n).Insert(0, s, n).ToString(); 
} 

uso es entonces:

text = "Hello World! ".Repeat(5); 
Cuestiones relacionadas