La mejor manera de repetir un personaje en C #

815

¿Cuál es la mejor manera de generar una cadena de \t's en C #?

Estoy aprendiendo C # y experimentando con diferentes formas de decir lo mismo.

Tabs(uint t)es una función que devuelve una stringcon tcantidad de \t's

Por ejemplo Tabs(3)devuelve"\t\t\t"

¿Cuál de estas tres formas de implementación Tabs(uint numTabs)es la mejor?

Por supuesto, eso depende de lo que significa "mejor".

  1. La versión LINQ tiene solo dos líneas, lo cual es bueno. Pero, ¿las llamadas a repetir y agregar consumen innecesariamente tiempo / recursos?

  2. La StringBuilderversión es muy clara, pero ¿la StringBuilderclase es más lenta?

  3. La stringversión es básica, lo que significa que es fácil de entender.

  4. ¿No importa en absoluto? ¿Son todos iguales?

Todas estas son preguntas para ayudarme a tener una mejor idea de C #.

private string Tabs(uint numTabs)
{
    IEnumerable<string> tabs = Enumerable.Repeat("\t", (int) numTabs);
    return (numTabs > 0) ? tabs.Aggregate((sum, next) => sum + next) : ""; 
}  

private string Tabs(uint numTabs)
{
    StringBuilder sb = new StringBuilder();
    for (uint i = 0; i < numTabs; i++)
        sb.Append("\t");

    return sb.ToString();
}  

private string Tabs(uint numTabs)
{
    string output = "";
    for (uint i = 0; i < numTabs; i++)
    {
        output += '\t';
    }
    return output; 
}
Alex Baranosky
fuente

Respuestas:

1492

¿Qué hay de esto?

string tabs = new String('\t', n);

¿Dónde nestá el número de veces que desea repetir la cadena?

O mejor:

static string Tabs(int n)
{
    return new String('\t', n);
}
CMS
fuente
2
¿Hay alguna manera de repetir esto por una palabra? en lugar de usar '\ t' cómo usar "tiempo"
asdfkjasdfjk
66
@ user1478137 O, mejor (también más abajo): esto
Xynariz
161
string.Concat(Enumerable.Repeat("ab", 2));

Devoluciones

"abab"

Y

string.Concat(Enumerable.Repeat("a", 2));

Devoluciones

"Automóvil club británico"

desde...

¿Hay una función incorporada para repetir string o char en .net?

Carter Medlin
fuente
1
¡Mejora haciéndolo sin Linq y con StruingBuilder!
Bitterblue
44
'' StringBuilder '' no es necesariamente más rápido stackoverflow.com/questions/585860/…
Schiavini
66
Puede que no sea más rápido, pero puede ahorrar en asignaciones de memoria (presión) si especifica la capacidad correcta por adelantado, y eso puede ser tan importante como el micro punto de referencia de perfilar esto.
wekempf
1
var strRepeat = string.Concat (Enumerable.Repeat ("ABC", 1000000)); // 50ms
yongfa365
1
@Pharap string.Joinfue más rápido en el ejemplo porque estaban usando un delimitador de espacio. string.Concates apropiado cuando no hay delimitador.
Carter Medlin
124

En todas las versiones de .NET, puede repetir una cadena así:

public static string Repeat(string value, int count)
{
    return new StringBuilder(value.Length * count).Insert(0, value, count).ToString();
}

Para repetir un personaje, new String('\t', count)es tu mejor apuesta. Vea la respuesta de @CMS .

Binoj Antony
fuente
77
Este es, con mucho, el rendimiento más rápido sabio para String. Otros métodos crean demasiada sobrecarga.
midspace
@midspace ¿Sabes si alguien ha explicado por qué las otras respuestas son peores? Asumiría el String nativo. Concat estaría tan optimizado internamente como StringBuilder
Marie
@Marie El siguiente artículo explica algunos de los méritos. support.microsoft.com/en-au/help/306822/… De lo contrario, hay otros dos factores, StringBuilder permite cadenas y no se limita a solo un carácter (aunque eso no pertenece a la pregunta original) y la cadena. La respuesta anterior de Concat tiene que crear una matriz primero usando Enumerable.Repeat. Como dije, es una sobrecarga innecesaria.
midspace
Supuse que no crearía una matriz primero porque podría iterar elemento por elemento. Gracias por el enlace, ¡lo leeré!
Marie
63

La mejor versión es ciertamente usar la forma integrada:

string Tabs(int len) { return new string('\t', len); }

De las otras soluciones, prefiera la más fácil; solo si esto resulta demasiado lento, busque una solución más eficiente.

Si usa un StringBuildery conoce de antemano su longitud resultante, entonces también use un constructor apropiado, esto es mucho más eficiente porque significa que solo se realiza una asignación que consume mucho tiempo y no se copian datos innecesariamente. Tonterías: por supuesto, el código anterior es más eficiente.

Konrad Rudolph
fuente
12
sb.Append ('\ t', len);
dan-gph
77
Mis puntos de referencia están demostrando new string('\t', len)ser entre 2x y 7x más rápidos que el StringBuilderenfoque. ¿Por qué crees que StringBuilderes más eficiente en este caso?
StriplingWarrior
66
@StriplingWarrior Gracias por corregir esto (después de haber estado aquí por dos años, ¡nada menos!).
Konrad Rudolph el
51

Métodos de extensión:

public static string Repeat(this string s, int n)
{
    return new String(Enumerable.Range(0, n).SelectMany(x => s).ToArray());
}

public static string Repeat(this char c, int n)
{
    return new String(c, n);
}
Rodrick Chapman
fuente
39
Érase una vez la gente solía hacer bucles
prabhakaran
2
@prabhakaran Estoy de acuerdo, pero la ventaja de Linq está en la comunicación; Casi siempre es trivial reimplementar una expresión de Linq usando construcciones imperativas.
Rodrick Chapman
10
Enumerable.Range(0, n).SelectMany(x => s)Puede ser reemplazado por un simple Enumerable.Repeat(s, n).
Palec
55
@Palec No, no puede. La SelectManyvoluntad para cada ficticio individual xda una secuencia de charvalores (desde los string simplementos IEnumerable<char>), y todas esas charsecuencias se concatenan en una charsecuencia larga . Lo que sugieras en cambio dará un IEnumerable<string>. No es lo mismo.
Jeppe Stig Nielsen
2
Me equivoqué, @JeppeStigNielsen. Gracias por el aviso. Si realmente quería utilizar Enumerable.Repeat, lo habría hecho para concatenar las cadenas juntas: string.Concat(Enumerable.Repeat(s, n)). Esto ya ha sido publicado antes .
Palec
40

¿Qué pasa con el uso del método de extensión?


public static class StringExtensions
{
   public static string Repeat(this char chatToRepeat, int repeat) {

       return new string(chatToRepeat,repeat);
   }
   public  static string Repeat(this string stringToRepeat,int repeat)
   {
       var builder = new StringBuilder(repeat*stringToRepeat.Length);
       for (int i = 0; i < repeat; i++) {
           builder.Append(stringToRepeat);
       }
       return builder.ToString();
   }
}

Entonces podrías escribir:

Debug.WriteLine('-'.Repeat(100)); // For Chars  
Debug.WriteLine("Hello".Repeat(100)); // For Strings

Tenga en cuenta que una prueba de rendimiento del uso de la versión del generador de cadenas para caracteres simples en lugar de cadenas le proporciona una gran penalidad de rendimiento: en mi computadora, la diferencia en el rendimiento medido es 1:20 entre: Debug.WriteLine ('-'. Repeat (1000000)) // versión de char y
Debug.WriteLine ("-". Repeat (1000000)) // versión de cadena

Ronnie
fuente
2
El rendimiento de la versión de cadena se puede mejorar mediante el uso StringBuilder.Insert(Int32, String, Int32), como respondió Binoj Anthony .
Palec
23

Qué tal esto:

//Repeats a character specified number of times
public static string Repeat(char character,int numberOfIterations)
{
    return "".PadLeft(numberOfIterations, character);
}

//Call the Repeat method
Console.WriteLine(Repeat('\t',40));
Denys Wessels
fuente
44
jaja ... eso es lo que podía pensar cuando caí en esta situación una vez. Pero personalmente encontré new string('\t', 10)la mejor solución
shashwat
Este truco también se usa en Essential C # 6.0 .
Programador orientado al dinero el
22

Sé que esta pregunta ya tiene cinco años, pero hay una manera simple de repetir una cadena que incluso funciona en .Net 2.0.

Para repetir una cadena:

string repeated = new String('+', 3).Replace("+", "Hello, ");

Devoluciones

"Hola hola hola, "

Para repetir una cadena como una matriz:

// Two line version.
string repeated = new String('+', 3).Replace("+", "Hello,");
string[] repeatedArray = repeated.Split(',');

// One line version.
string[] repeatedArray = new String('+', 3).Replace("+", "Hello,").Split(',');

Devoluciones

{"Hola hola hola", ""}

Mantenlo simple.

ChaimG
fuente
19

Digamos que desea repetir '\ t' n número de veces, puede usar;

String.Empty.PadRight(n,'\t')
Amin
fuente
1
Gracias. Esto también es muy rápido. codereview.stackexchange.com/questions/36391/…
Sunsetquest
Siempre lo he hecho de esta manera. Incluso si está envuelto en un método de extensión, es más simple que otras implementaciones publicadas aquí. Tenga en cuenta que OP solo quería repetir \ t, no cadenas.
Michael Ribbons
17

Su primer ejemplo que usa Enumerable.Repeat:

private string Tabs(uint numTabs)
{
    IEnumerable<string> tabs = Enumerable.Repeat(
                                 "\t", (int) numTabs);
    return (numTabs > 0) ? 
            tabs.Aggregate((sum, next) => sum + next) : ""; 
} 

se puede reescribir de manera más compacta con String.Concat:

private string Tabs(uint numTabs)
{       
    return String.Concat(Enumerable.Repeat("\t", (int) numTabs));
}
Rayo
fuente
14

Usar String.Concaty Enumerable.Repeatque será menos costoso que usarString.Join

public static Repeat(this String pattern, int count)
{
    return String.Concat(Enumerable.Repeat(pattern, count));
}
bradgonesurfing
fuente
9
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());
wb
fuente
4

La respuesta realmente depende de la complejidad que desee. Por ejemplo, quiero delinear todas mis sangrías con una barra vertical, por lo que mi cadena de sangría se determina de la siguiente manera:

return new string(Enumerable.Range(0, indentSize*indent).Select(
  n => n%4 == 0 ? '|' : ' ').ToArray());
Dmitri Nesteruk
fuente
3

Y otro método más

new System.Text.StringBuilder().Append('\t', 100).ToString()
Artyom
fuente
Pasar la longitud de cadena resultante al StringBuilderconstructor ahorra reasignación. Aún así, esto es más hablador y menos eficiente que usar el stringconstructor que puede repetir un carácter dado, como ya se muestra en la respuesta aceptada.
Palec
3

Para mi esta bien:

public static class Utils
{
    public static string LeftZerosFormatter(int zeros, int val)
    {
        string valstr = val.ToString();

        valstr = new string('0', zeros) + valstr;

        return valstr.Substring(valstr.Length - zeros, zeros);
    }
}
Ángel Ibáñez
fuente
2

Puedes crear un método de extensión

static class MyExtensions
{
    internal static string Repeat(this char c, int n)
    {
        return new string(c, n);
    }
}

Entonces puedes usarlo así

Console.WriteLine('\t'.Repeat(10));
ivan
fuente
1

Sin duda, la respuesta aceptada es la mejor y más rápida forma de repetir un solo personaje.

La respuesta de Binoj Anthony es una forma simple y bastante eficiente de repetir una cadena.

Sin embargo, si no le importa un poco más de código, puede usar mi técnica de relleno de matriz para crear estas cadenas de manera eficiente aún más rápido. En mis pruebas de comparación, el siguiente código se ejecutó en aproximadamente el 35% del tiempo del código StringBuilder.Insert.

public static string Repeat(this string value, int count)
{
    var values = new char[count * value.Length];
    values.Fill(value.ToCharArray());
    return new string(values);
}

public static void Fill<T>(this T[] destinationArray, params T[] value)
{
    if (destinationArray == null)
    {
        throw new ArgumentNullException("destinationArray");
    }

    if (value.Length > destinationArray.Length)
    {
        throw new ArgumentException("Length of value array must not be more than length of destination");
    }

    // set the initial array value
    Array.Copy(value, destinationArray, value.Length);

    int copyLength, nextCopyLength;

    for (copyLength = value.Length; (nextCopyLength = copyLength << 1) < destinationArray.Length; copyLength = nextCopyLength)
    {
        Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
    }

    Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}

Para obtener más información sobre esta técnica de relleno de matriz, consulte la forma más rápida de llenar una matriz con un solo valor

Grax32
fuente
0

Prueba esto:

  1. Agregar referencia Microsoft.VisualBasic
  2. Uso: Resultado de cadena = Microsoft.VisualBasic.Strings.StrDup (5, "hola");
  3. Avísame si te funciona.
Toso Pankovski
fuente
Agregar dependencia de otro ensamblaje y la necesidad de cargarlo no es razonable en la mayoría de los casos cuando necesita dicha funcionalidad. Aún así, es bueno saber que existe tal cosa en .NET.
Palec
Hay muchos pros y contras en diferentes contextos, por lo que todos deberían decidir según la situación en la que se encuentre.
Toso Pankovski
-1

Aunque es muy similar a una sugerencia anterior, me gusta mantenerlo simple y aplicar lo siguiente:

string MyFancyString = "*";
int strLength = 50;
System.Console.WriteLine(MyFancyString.PadRight(strLength, "*");

Estándar .Net realmente,

Gordo
fuente
Simplemente agregará relleno, no se repite
levi