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 "---------".
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); // -----
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).
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;
}
}
solution la plus performante pour cordes
string result = new StringBuilder().Insert(0, "---", 5).ToString();
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
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:
StringBuilder
par le biais de la préallocation de stockage.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();
}
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))
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.
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());
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;
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);
}
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.
Console.Write(new string('=', 30) + "\n");
==============================
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());
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}");
}
}
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.