web-dev-qa-db-fra.com

Existe-t-il un moyen facile de renvoyer une chaîne répétée X fois?

J'essaie d'insérer un certain nombre d'indentations avant une chaîne en fonction de la profondeur des éléments et je me demande s'il existe un moyen de renvoyer une chaîne répétée X fois. Exemple:

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 "---------".
256
Abe Miessler

Si vous souhaitez uniquement répéter le même caractère, vous pouvez utiliser le constructeur string qui accepte un caractère et le nombre de répétitions nécessaires new String(char c, int count).

Par exemple, pour répéter un tiret cinq fois:

string result = new String('-', 5); // -----
453
Ahmad Mageed

Si vous utilisez .NET 4.0, vous pouvez utiliser string.Concat avec Enumerable.Repeat .

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

Sinon, je choisirais quelque chose comme réponse d'Adam .

La raison pour laquelle généralement je ne voudrais pas conseiller d'utiliser réponse de Andrey est simplement que l'appel ToArray() introduit une surcharge superflue qui est évité avec l'approche StringBuilder proposée par Adam. Cela dit, au moins, cela fonctionne sans nécessiter .NET 4.0; et c'est rapide et facile (et ça ne va pas vous tuer si l'efficacité n'est pas une préoccupation majeure).

246
Dan Tao
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;
    }
}
40
Adam Robinson

solution la plus performante pour cordes

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

Utilisez String.PadLeft , si la chaîne souhaitée ne contient qu'un seul caractère.

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

Crédit dû ici

19
Steve Townsend

Pour de nombreux scénarios, c'est probablement la solution la plus simple:

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

L'utilisation est alors:

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

Cela s'appuie sur d'autres réponses (en particulier les @ c0rd). Outre sa simplicité, il présente les caractéristiques suivantes, que toutes les autres techniques présentées ne partagent pas:

  • Répétition d'une chaîne de n'importe quelle longueur, pas seulement d'un caractère (comme demandé par l'OP).
  • Utilisation efficace de StringBuilder par le biais de la préallocation de stockage.
14
Bob Sammers

J'irais chercher la réponse de Dan Tao, mais si vous n'utilisez pas .NET 4.0, vous pouvez procéder de la sorte

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

Vous pouvez répéter votre chaîne (au cas où ce ne serait pas un seul caractère) et concatter le résultat, comme ceci:

String.Concat(Enumerable.Repeat("---", 5))
6
liron

J'aime la réponse donnée. Voici ce que j'ai utilisé par le passé:

"" .PadLeft (3 * Indent, '-')

Cela permettra de créer un retrait, mais techniquement, la question était de répéter une chaîne. Si le retrait de la chaîne ressemble à quelque chose comme> - <, cela ne fonctionnera pas, ainsi que la réponse acceptée. Dans ce cas, la solution de c0rd utilisant stringbuilder a l'air bien, bien que les frais généraux de stringbuilder ne le rendent peut-être pas le plus performant. Une option consiste à créer un tableau de chaînes, à le remplir de chaînes de retrait, puis à le concaténer. À blanc:

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

Nous aimons tous une solution intelligente, mais parfois simple est le meilleur. 

2
Londo Mollari
        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());
2
Andrey

Je ne sais pas comment cela fonctionnerait, mais c'est un morceau de code facile. (J'ai probablement fait paraître cela plus compliqué qu'il ne l'est.) 

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

Alternativement, si vous connaissez le nombre maximum de niveaux que vous pouvez espérer, vous pouvez simplement déclarer un tableau et y indexer. Vous voudrez probablement rendre ce tableau statique ou constant.

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

Surpris, personne n'est allé à la vieille école. Je ne fais pas aucune réclamations à propos de ce code, mais juste pour le fun:

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

Je n'ai pas assez de rep pour commenter la réponse d'Adam, mais la meilleure façon de le faire est la suivante:

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

Vous devez vérifier si numTimes est supérieur à zéro, sinon vous obtiendrez une exception.

1
Gru

Imprimer une ligne avec répétition.

Console.Write(new string('=', 30) + "\n");

==============================

0
Kamal

Une autre approche consiste à considérer string comme IEnumerable<char> et à utiliser une méthode d'extension générique qui multipliera les éléments d'une collection par le facteur spécifié.

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

Donc dans votre cas:

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

Je n'ai pas vu cette solution. Je trouve cela plus simple pour ma situation actuelle en développement logiciel:

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

Pour une utilisation générale, les solutions impliquant la classe StringBuilder conviennent mieux à la répétition de chaînes de plusieurs caractères. Il est optimisé pour gérer la combinaison d'un grand nombre de chaînes de manière telle qu'une concaténation simple ne le peut pas et qu'il serait difficile voire impossible de le faire plus efficacement à la main. Les solutions StringBuilder présentées ici utilisent O(N) itérations à compléter, un taux forfaitaire proportionnel au nombre de répétitions.

Cependant, pour un très grand nombre de répétitions, ou lorsque des niveaux d'efficacité élevés doivent être évités, une meilleure approche consiste à faire quelque chose de similaire aux fonctionnalités de base de StringBuilder mais à produire des copies supplémentaires à partir de la destination plutôt qu'à partir de la chaîne d'origine. comme ci-dessous.

    public static string Repeat_CharArray_LogN(this string str, int times)
    {
        int limit = (int)Math.Log(times, 2);
        char[] buffer = new char[str.Length * times];
        int width = str.Length;
        Array.Copy(str.ToCharArray(), buffer, width);

        for (int index = 0; index < limit; index++)
        {
            Array.Copy(buffer, 0, buffer, width, width);
            width *= 2;
        }
        Array.Copy(buffer, 0, buffer, width, str.Length * times - width);

        return new string(buffer);
    }

Cela double la longueur de la chaîne source/destination à chaque itération, ce qui évite la surcharge de la réinitialisation des compteurs chaque fois qu'il passe par la chaîne d'origine, au lieu de la lecture et de la copie en douceur de la chaîne désormais beaucoup plus longue, ce que les processeurs modernes peuvent faire beaucoup plus efficacement.

Il utilise un logarithme en base 2 pour déterminer le nombre de fois nécessaire pour doubler la longueur de la chaîne, puis le multiplie par la suite. Étant donné que le reste à copier est maintenant inférieur à la longueur totale à partir de laquelle il copie, il peut alors simplement copier un sous-ensemble de ce qu'il a déjà généré.

J'ai utilisé la méthode Array.Copy () sur l'utilisation de StringBuilder, car une copie du contenu de StringBuilder sur lui-même entraînerait la surcharge de produire une nouvelle chaîne avec ce contenu à chaque itération. Array.Copy () évite cela, tout en fonctionnant avec un taux d'efficacité extrêmement élevé.

Cette solution prend O (1 + log N) itérations à compléter, un taux qui augmente logarithmiquement avec le nombre de répétitions (doubler le nombre de répétitions équivaut à une itération supplémentaire), une économie substantielle par rapport aux autres méthodes, qui augmentent proportionnellement.

0
bükWyrm