Melhor maneira de repetir um caractere em C #

815

Qual é a melhor maneira de gerar uma sequência de \t's em c #

Estou aprendendo c # e experimentando maneiras diferentes de dizer a mesma coisa.

Tabs(uint t)é uma função que retorna a stringcom tquantidade de \t's

Por exemplo, Tabs(3)retorna"\t\t\t"

Qual dessas três maneiras de implementar Tabs(uint numTabs)é a melhor?

Claro que isso depende do que "melhor" significa.

  1. A versão do LINQ é de apenas duas linhas, o que é legal. Mas as chamadas para Repetir e Agregar desnecessariamente consomem tempo / recursos?

  2. A StringBuilderversão é muito clara, mas a StringBuilderclasse é de alguma forma mais lenta?

  3. A stringversão é básica, o que significa que é fácil de entender.

  4. Isso não importa? Eles são todos iguais?

Essas são perguntas para me ajudar a ter uma idéia melhor do 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
fonte

Respostas:

1492

Que tal isso:

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

Onde né o número de vezes que você deseja repetir a sequência.

Ou melhor:

static string Tabs(int n)
{
    return new String('\t', n);
}
CMS
fonte
2
existe alguma maneira de repetir isso por uma palavra? em vez de usar '\ t' como usar o "tempo"
asdfkjasdfjk
6
@ user1478137 Ou, melhor (também mais abaixo): esta
Xynariz
161
string.Concat(Enumerable.Repeat("ab", 2));

Devoluções

"abab"

E

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

Devoluções

"aa"

de...

Existe uma função interna para repetir string ou char no .net?

Carter Medlin
fonte
1
Faça melhor sem Linq e with StruingBuilder!
Bitterblue
4
'StringBuilder' não é necessariamente mais rápido stackoverflow.com/questions/585860/…
Schiavini
6
Pode não ser mais rápido, mas pode economizar alocações de memória (pressão) se você especificar a capacidade correta antecipadamente, e isso pode ser tão importante quanto a micro referência de criação de perfil disso.
wekempf
1
var strRepeat = string.Concat (Enumerable.Repeat ("ABC", 1000000)); // 50ms
yongfa365
1
O @Pharap string.Joinfoi mais rápido no exemplo, porque eles estavam usando um delimitador de espaço. string.Concaté apropriado quando não há delimitador.
Carter Medlin
124

Em todas as versões do .NET, você pode repetir uma string assim:

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

Repetir um personagem new String('\t', count)é a sua melhor aposta. Veja a resposta do @CMS .

Binoj Antony
fonte
7
Este é de longe o desempenho mais rápido para o String. Outros métodos criam muita sobrecarga.
Midspace 11/11/15
@midspace Você sabe se alguém explicou por que as outras respostas são piores? Eu teria assumido o String.Concat nativa seria tão otimizado internamente como StringBuilder
Marie
@ Marie O artigo a seguir explica alguns dos méritos. support.microsoft.com/en-au/help/306822/… Caso contrário, outros dois fatores são: o StringBuilder permite seqüências de caracteres e não se limita apenas a um caractere (embora isso não pertença à pergunta original) e à seqüência de caracteres. A resposta da Concat acima deve primeiro criar uma matriz usando Enumerable.Repeat. Como eu disse, é uma sobrecarga desnecessária.
Midspace 26/03/19
Eu tinha assumido que não criaria uma matriz primeiro porque poderia apenas iterar item por item. Obrigado pelo link, vou dar uma leitura!
2777 Marie
63

A melhor versão é certamente usar da maneira integrada:

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

Das outras soluções, prefira as mais fáceis; somente se isso estiver muito lento, lute por uma solução mais eficiente.

Se você usa um StringBuildere conhece seu comprimento resultante com antecedência, também usa um construtor apropriado, isso é muito mais eficiente, pois significa que apenas uma alocação demorada ocorre e nenhuma cópia desnecessária de dados. Bobagem: é claro que o código acima é mais eficiente.

Konrad Rudolph
fonte
12
sb.Append ('\ t', len);
Dan-gph
7
Meus benchmarks estão mostrando new string('\t', len)estar entre 2x e 7x mais rápidos que a StringBuilderabordagem. Por que você acha que StringBuilderé mais eficiente nesse caso?
StriplingWarrior
6
@StriplingWarrior Obrigado por corrigir isso (depois de estar aqui há dois anos, nem menos!).
Konrad Rudolph
51

Métodos de extensão:

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
fonte
39
Era uma vez que as pessoas usavam loops
260013 prabhakaran
2
@prabhakaran Concordo, mas a vantagem do Linq está na comunicação; quase sempre é trivial reimplementar uma expressão Linq usando construções imperativas.
Rodrick Chapman
10
Enumerable.Range(0, n).SelectMany(x => s)pode ser substituído por um simples Enumerable.Repeat(s, n).
Palec 9/04
5
@Palec Não, não pode. A SelectManyvontade de cada manequim único xfornece uma sequência de charvalores (desde os string simplementos IEnumerable<char>) e todas essas charsequências são concatenadas em uma charsequência longa . O que você sugere dará um IEnumerable<string>. Não é o mesmo.
Jeppe Stig Nielsen
2
Eu estava errado, @JeppeStigNielsen. Obrigado pelo aviso. Se eu realmente queria usar Enumerable.Repeat, eu teria que concatenar as cordas em conjunto: string.Concat(Enumerable.Repeat(s, n)). Isso já foi publicado antes .
Palec 24/12
40

Que tal usar o método de extensão?


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

Você pode então escrever:

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

Observe que um teste de desempenho do uso da versão stringbuilder para caracteres simples em vez de seqüências de caracteres fornece uma grande penalidade de desempenho: no meu computador, a diferença no desempenho medido é 1:20 entre: Debug.WriteLine ('-'. Repeat (1000000)) // versão char e
Debug.WriteLine ("-". Repeat (1000000)) // string version

Ronnie
fonte
2
O desempenho da versão da string pode ser aprimorado usando StringBuilder.Insert(Int32, String, Int32), como Binoj Anthony respondeu .
Palec
23

Que tal agora:

//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
fonte
4
haha .. foi nisso que pude pensar quando caí nessa situação uma vez. Mas pessoalmente eu encontrei new string('\t', 10)para ser a melhor solução
Shashwat
Esse truque também é usado no Essential C # 6.0 .
Programador Orientado a Dinheiro
22

Eu sei que essa pergunta já tem cinco anos, mas existe uma maneira simples de repetir uma string que até funciona no .Net 2.0.

Para repetir uma sequência:

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

Devoluções

"Ola Ola Ola, "

Para repetir uma sequência como uma 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(',');

Devoluções

{"Ola Ola Ola", ""}

Mantenha simples.

ChaimG
fonte
19

Digamos que você queira repetir '\ t' n número de vezes, você pode usar;

String.Empty.PadRight(n,'\t')
Amin
fonte
1
Obrigado. Isso também é muito rápido. codereview.stackexchange.com/questions/36391/...
Sunsetquest
Eu sempre fiz dessa maneira. Mesmo se envolvido em um método de extensão, é mais simples do que outras implementações postadas aqui. Observe que o OP só queria repetir \ t, não seqüências de caracteres.
Michael fitas
17

Seu primeiro exemplo 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) : ""; 
} 

pode ser reescrito de forma mais compacta com String.Concat:

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

Usando String.Concate Enumerable.Repeatque será mais barato do que usarString.Join

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

A resposta realmente depende da complexidade que você deseja. Por exemplo, quero delinear todos os meus recuos com uma barra vertical, para que minha cadeia de recuos seja determinada da seguinte maneira:

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

E ainda outro método

new System.Text.StringBuilder().Append('\t', 100).ToString()
Artyom
fonte
Passar o comprimento da string resultante para o StringBuilderconstrutor salva a realocação. Ainda assim, isso é mais falador e menos eficiente do que usar o stringconstrutor que pode repetir um determinado caractere, como já mostrado na resposta aceita.
Palec
3

Para mim está bem:

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
fonte
2

Você pode criar um método de extensão

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

Então você pode usá-lo assim

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

Sem dúvida, a resposta aceita é a melhor e mais rápida maneira de repetir um único caractere.

A resposta de Binoj Anthony é uma maneira simples e bastante eficiente de repetir uma string.

No entanto, se você não se importa com um pouco mais de código, pode usar minha técnica de preenchimento de matriz para criar essas seqüências com eficiência ainda mais rapidamente. Nos meus testes de comparação, o código abaixo é executado em cerca de 35% do tempo do 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 saber mais sobre esta técnica de preenchimento de matriz, consulte Maneira mais rápida de preencher uma matriz com um único valor

Grax32
fonte
0

Tente o seguinte:

  1. Adicionar referência Microsoft.VisualBasic
  2. Use: String result = Microsoft.VisualBasic.Strings.StrDup (5, "oi");
  3. Deixe-me saber se funciona para você.
Toso Pankovski
fonte
Adicionar dependência a outro assembly e a necessidade de carregá-lo não é razoável na maioria dos casos, quando você precisa dessa funcionalidade. Ainda assim, é bom saber que existe isso no .NET.
Palec
Há muitos prós e contras em diferentes contextos, para que todos devem decidir, dependendo da situação que ele / ela está.
Toso Pankovski
-1

Embora muito parecido com uma sugestão anterior, eu gosto de simplificar e aplicar o seguinte:

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

Standard .Net realmente,

Porky
fonte
Ela só vai adicionar preenchimento, não se repita
levi