Meilleure façon de répéter un caractère en C #


815

Quelle est la meilleure façon de générer une chaîne de \t'en C #

J'apprends le C # et j'expérimente différentes façons de dire la même chose.

Tabs(uint t)est une fonction qui renvoie une stringavec tquantité de \t« s

Par exemple, Tabs(3)retourne"\t\t\t"

Laquelle de ces trois façons de mettre en œuvre Tabs(uint numTabs)est la meilleure?

Bien sûr, cela dépend de ce que signifie le "meilleur".

  1. La version LINQ n'est que de deux lignes, ce qui est bien. Mais les appels à Répéter et à Agréger prennent-ils inutilement du temps / des ressources?

  2. La StringBuilderversion est très claire mais la StringBuilderclasse est-elle en quelque sorte plus lente?

  3. La stringversion est basique, ce qui signifie qu'elle est facile à comprendre.

  4. Cela n'a-t-il aucune importance? Sont-ils tous égaux?

Ce sont toutes des questions pour m'aider à mieux comprendre 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; 
}

Réponses:


1492

Et ça:

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

nest le nombre de fois que vous souhaitez répéter la chaîne.

Ou mieux:

static string Tabs(int n)
{
    return new String('\t', n);
}

2
est-il possible de répéter cela pour un mot? au lieu d'utiliser '\ t' comment utiliser "time"
asdfkjasdfjk

6
@ user1478137 Ou, mieux (aussi plus bas): ceci
Xynariz

161
string.Concat(Enumerable.Repeat("ab", 2));

Retour

"abab"

Et

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

Retour

"aa"

de...

Existe-t-il une fonction intégrée pour répéter la chaîne ou le caractère dans .net?


1
Améliorez-le en le faisant sans Linq et avec StruingBuilder!
Bitterblue

4
'' StringBuilder '' n'est pas nécessairement plus rapide stackoverflow.com/questions/585860/…
Schiavini

6
Ce n'est peut-être pas plus rapide, mais cela peut économiser sur les allocations de mémoire (pression) si vous spécifiez la capacité correcte à l'avance, et cela peut être aussi important que le micro-repère de profilage.
wekempf

1
var strRepeat = string.Concat (Enumerable.Repeat ("ABC", 1000000)); // 50ms
yongfa365

1
@Pharap string.Joinétait plus rapide dans l'exemple car ils utilisaient un délimiteur d'espace. string.Concatest approprié lorsqu'il n'y a pas de délimiteur.
Carter Medlin

124

Dans toutes les versions de .NET, vous pouvez répéter une chaîne ainsi:

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

Pour répéter un personnage, new String('\t', count)c'est votre meilleur pari. Voir la réponse de @CMS .


7
C'est de loin la performance la plus rapide pour String. D'autres méthodes créent trop de surcharge.
midspace

@midspace Savez-vous si quelqu'un a expliqué pourquoi les autres réponses sont pires? J'aurais supposé que le String.Concat natif serait tout aussi optimisé en interne que StringBuilder
Marie

@Marie L'article suivant explique certains des mérites. support.microsoft.com/en-au/help/306822/… Sinon, deux autres facteurs sont, StringBuilder autorise les chaînes et n'est pas limité à un simple caractère (bien que cela ne se rapporte pas à la question d'origine), et la chaîne. La réponse concat ci-dessus doit d'abord créer un tableau en utilisant Enumerable.Repeat. Comme je l'ai dit, ce sont des frais généraux inutiles.
midspace

J'avais supposé qu'il ne créerait pas un tableau en premier car il pourrait simplement itérer élément par élément. Merci pour le lien, je vais lui donner lecture!
Marie

63

La meilleure version est certainement d'utiliser la méthode intégrée:

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

Parmi les autres solutions, préférez la plus simple; seulement si cela s'avère trop lent, essayez une solution plus efficace.

Si vous utilisez un StringBuilder et connaissez sa longueur résultante à l'avance, puis utilisez également un constructeur approprié, cela est beaucoup plus efficace car cela signifie qu'une seule allocation chronophage a lieu, et aucune copie inutile des données. Non-sens: bien sûr, le code ci-dessus est plus efficace.


12
sb.Append ('\ t', len);
dan-gph

7
Mes repères se révèlent new string('\t', len)être entre 2x et 7x plus rapides que l' StringBuilderapproche. Pourquoi pensez-vous StringBuilderest plus efficace dans ce cas?
StriplingWarrior

6
@StriplingWarrior Merci d'avoir corrigé cela (après deux ans de présence ici, rien de moins!).
Konrad Rudolph

51

Méthodes d'extension:

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

39
Il était une fois les gens utilisaient des boucles
prabhakaran

2
@prabhakaran Je suis d'accord mais l'avantage de Linq réside dans la communication; il est presque toujours trivial de réimplémenter une expression Linq en utilisant des constructions impératives.
Rodrick Chapman

10
Enumerable.Range(0, n).SelectMany(x => s)peut être remplacé par un simple Enumerable.Repeat(s, n).
Palec

5
@Palec Non, il ne peut pas. La SelectManyvolonté de chaque mannequin xdonne une séquence de charvaleurs (depuis les string simplémentations IEnumerable<char>), et toutes ces charséquences sont concaténées en une longue charséquence. Ce que vous proposez donnera plutôt un IEnumerable<string>. Ce n'est pas pareil.
Jeppe Stig Nielsen

2
J'avais tort, @JeppeStigNielsen. Merci pour l'information. Si je voulais vraiment utiliser Enumerable.Repeat, je concaténer les chaînes ensemble: string.Concat(Enumerable.Repeat(s, n)). Cela a déjà été publié auparavant .
Palec

40

Qu'en est-il de l'utilisation de la méthode d'extension?


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

Vous pourriez alors écrire:

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

Notez qu'un test de performance d'utilisation de la version stringbuilder pour des caractères simples au lieu de chaînes vous donne une pénalité de préformance majeure: sur mon ordinateur, la différence de performances mesurées est de 1:20 entre: Debug.WriteLine ('-'. Repeat (1000000)) // version char et
Debug.WriteLine ("-". Repeat (1000000)) // version chaîne


2
Les performances de la version chaîne peuvent être améliorées en utilisant StringBuilder.Insert(Int32, String, Int32), comme Binoj Anthony a répondu .
Palec

23

Que dis-tu de ça:

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

4
haha .. c'est ce à quoi je pouvais penser quand je suis tombé dans cette situation une fois. Mais personnellement, j'ai trouvé que new string('\t', 10)c'était la meilleure solution
shashwat

Cette astuce est également utilisée dans Essential C # 6.0 .
Programmeur orienté argent

22

Je sais que cette question a déjà cinq ans, mais il existe un moyen simple de répéter une chaîne qui fonctionne même dans .Net 2.0.

Pour répéter une chaîne:

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

Retour

"Bonjour bonjour bonjour, "

Pour répéter une chaîne sous forme de tableau:

// 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(',');

Retour

{"Bonjour bonjour bonjour", ""}

Rester simple.


19

Disons que vous voulez répéter '\ t' n nombre de fois, vous pouvez utiliser;

String.Empty.PadRight(n,'\t')


Je l'ai toujours fait de cette façon. Même s'il est enveloppé dans une méthode d'extension, il est plus simple que les autres implémentations publiées ici. Notez que OP ne voulait que répéter \ t, pas des chaînes.
Michael Ribbons

17

Votre premier exemple qui utilise Enumerable.Repeat:

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

peut être réécrit de manière plus compacte avec String.Concat:

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

14

Utiliser String.Concatet Enumerable.Repeatqui sera moins cher que d'utiliserString.Join

public static Repeat(this String pattern, int count)
{
    return String.Concat(Enumerable.Repeat(pattern, count));
}

9
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());

4

La réponse dépend vraiment de la complexité que vous souhaitez. Par exemple, je veux décrire tous mes retraits avec une barre verticale, donc ma chaîne de retrait est déterminée comme suit:

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

3

Et encore une autre méthode

new System.Text.StringBuilder().Append('\t', 100).ToString()

Passer la longueur de chaîne résultante au StringBuilderconstructeur enregistre la réallocation. Pourtant, c'est plus bavard et moins efficace que d'utiliser le stringconstructeur qui peut répéter un caractère donné, comme déjà montré dans la réponse acceptée.
Palec

3

Pour moi, c'est 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);
    }
}

2

Vous pouvez créer une méthode d'extension

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

Ensuite, vous pouvez l'utiliser comme ceci

Console.WriteLine('\t'.Repeat(10));

1

Sans aucun doute, la réponse acceptée est le moyen le meilleur et le plus rapide de répéter un seul caractère.

La réponse de Binoj Anthony est un moyen simple et assez efficace de répéter une chaîne.

Cependant, si cela ne vous dérange pas un peu plus de code, vous pouvez utiliser ma technique de remplissage de tableau pour créer efficacement ces chaînes encore plus rapidement. Dans mes tests de comparaison, le code ci-dessous exécuté dans environ 35% du temps du code 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);
}

Pour plus d'informations sur cette technique de remplissage de tableau, voir Méthode la plus rapide pour remplir un tableau avec une seule valeur


0

Essaye ça:

  1. Ajouter une référence Microsoft.VisualBasic
  2. Utilisation: String result = Microsoft.VisualBasic.Strings.StrDup (5, "hi");
  3. Dites-moi si cela marche pour vous.

Ajouter la dépendance à un autre assembly et la nécessité de le charger est déraisonnable dans la plupart des cas lorsque vous avez besoin d'une telle fonctionnalité. Pourtant, bon de savoir qu'il existe une telle chose dans .NET.
Palec

Il y a de nombreux avantages et inconvénients dans différents contextes, donc tout le monde devrait décider en fonction de la situation dans laquelle il se trouve.
Toso Pankovski

-1

Bien que très similaire à une suggestion précédente, j'aime rester simple et appliquer ce qui suit:

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

Standard .Net vraiment,


Il ne fera qu'ajouter du rembourrage, ne se répète pas
levi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.